typescript - Nuxt-plugin-egenskap finns inte på typen 'CombinedVueInstance'
Jag har skapat ett plugin och vill använda det i en av mina komponenter. Koden från pluginet finns under ~/plugins/socket.client.ts:
import { io } from 'socket.io-client'
import { Plugin } from '@nuxt/types'
const socketIOPlugin: Plugin = (_, inject) => {
const socketUrl: string | undefined = process.env.socket_url
if (!socketUrl || socketUrl.length <= 0) {
throw new Error('socketUrl is undefined.')
}
const socket = io(socketUrl)
inject('socket', socket)
}
export default socketIOPlugin
Det är registrerat i nuxt.config.js. plugins: ['~/plugins/socket.client']
Och jag använder det inuti min komponent så här:
import Vue from 'vue'
export default Vue.extend({
mounted() {
this.$socket.on("example:hello", (data: any) => {
console.log(data);
});
},
})
Men när jag startar nuxt får jag följande fel: Property '$socket' does not exist on type 'CombinedVueInstance<Vue, unknown, unknown, unknown, Readonly<Record<never, any>>>'.
Jag har redan försökt lägga till en vue-shim.d.ts-fil, men fortfarande förändras ingenting.
declare module "*.vue" {
import Vue from 'vue'
export default Vue
}
declare module "vue/types/vue" {
import { Socket } from "socket.io-client";
interface Vue {
$socket: Socket;
}
}
Jag verkar inte kunna hitta ett sätt att lösa detta. Kan någon vänligen hjälpa mig?
Svar #1
Jag har äntligen fått det att fungera genom att omstrukturera min kod lite.
Ansvarsfriskrivning; Denna lösning fungerar för mig eftersom den låter mig använda pluginet på ett annat sätt. Det är inte specifikt svaret på frågan. Svaret på denna fråga kan uppnås genom att använda plugin-koden nedan och ändra index.d.ts lite så att $socket också är åtkomlig inne i Vue-komponenterna. Läs mer om detta här.
~/plugins/socket.client.tsimport { Plugin } from '@nuxt/types'
import { io, Socket } from 'socket.io-client'
function getSocketConnection(): Socket {
const socketUrl: string | undefined = process.env.socket_url
if (!socketUrl || socketUrl.length <= 0) {
throw new Error('socketUrl is undefined.')
}
return io(socketUrl)
}
const socketIOPlugin: Plugin = (_, inject) => {
inject('socket', getSocketConnection())
}
export default socketIOPlugin
export const socket = getSocketConnection()
Jag har också bytt namn på vue-shim.d.ts till bara index.d.ts och lagt till följande rader:
import { accessorType } from '~/store'
import { socket } from '~/plugins/socket.client'
declare module 'vuex/types/index' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Store<S> {
$socket: typeof socket
}
}
declare module 'vue/types/vue' {
interface Vue {
$accessor: typeof accessorType
}
}
declare module '@nuxt/types' {
interface NuxtAppOptions {
$accessor: typeof accessorType
}
}
Istället för att använda socket.io-pluginet inuti mina komponenter, har jag skapat en store ~/store/index.ts som hanterar alla socket-händelser.
import type { ActionTree, GetterTree, MutationTree } from 'vuex'
import { getAccessorType } from 'typed-vuex'
export const state = () => ({
posts: [] as any[],
})
export type RootState = ReturnType<typeof state>
export const getters: GetterTree<RootState, RootState> = {
posts: (state) => state.posts,
}
export const mutations: MutationTree<RootState> = {
SET_POSTS: (state: RootState, posts: any[]) => (state.posts = posts),
}
export const actions: ActionTree<RootState, RootState> = {
fetchPosts({ commit }) {
this.$socket.emit('example:getPosts')
this.$socket.once('example:posts', (data: any) => {
commit('SET_POSTS', data)
})
},
}
export const accessorType = getAccessorType({
state,
getters,
mutations,
actions,
modules: {},
})
Användningen är nu mycket enklare och allt uppdateras som det ska med vuex.
~/pages/index.vue<script lang='ts'>
import { Component, Vue } from 'nuxt-property-decorator'
@Component
export default class Index extends Vue {
get posts() {
return this.$accessor.posts
}
fetchPosts() {
this.$accessor.fetchPosts()
}
}
</script>
För att få allt att fungera behöver du installera följande npm-paket:
- @nuxt/typer
- typad-vuex
- vue-klass-komponent
- nuxt-egenskaps-dekoratör
- nuxt-typed-vuex (Glöm inte att lägga till detta i din nuxt.config.ts buildModules)
Svar #2
declare module "vue/types/vue" är en modulförstärkning - för att förstärkning ska fungera korrekt måste den placeras i TS-filen som innehåller minst en top-nivå import/export (mer information här)
Så mitt förslag är att flytta den koden från vue-shim.d.ts direkt till socket.client.ts
