Open herkulano opened 6 years ago
This is because Vue.extend
is expecting an object that satisfies the ComponentOptions interface defined in Vue's types.
Since asyncData
, fetch
etc. are all mixed in by Nuxt, you will need to augment the ComponentOptions
interface defined by Vue (I don't think there are types available from Nuxt yet).
To augment existing TS interfaces within other modules, you need to create a file ending in .d.ts
(know as a declaration file) then declare the module you want to augment. I generally create one declaration file per module—so in this case it would be nuxt.d.ts
. I also generally put these declaration files in a types
directory alongside the other directories, so you would have a dir structure that looked something like this:
pages
- index.vue
types
- nuxt.d.ts
Then the contents of nuxt.d.ts
would look something like this:
declare module "vue" {
import Vue, { ComponentOptions } from "vue"
import { Route } from "vue-router"
import { Store } from "vuex"
// https://nuxtjs.org/api/context
export interface NuxtContext<V extends Vue> {
app: V
isClient: boolean
isServer: boolean
isStatic: boolean
isDev: boolean
isHMR: boolean
route: Route
store: Store
env: object
params: object
query: object
// ...add remaining interface here
}
// https://nuxtjs.org/api/pages-fetch
export interface ComponentOptions<V extends Vue> {
asyncData?(context: NuxtContext<V>): Promise<object> | object
fetch?(context: NuxtContext<V>): Promise<object> | object
// ...add remaining interface here
}
}
NOTE 1: It's important that this file is included in the matched files as defined in your tsconfig.json
file—otherwise TS won't pick it up.
NOTE 2: I have not tested the above implementation of these "ambient types" so you will probably have to play around a little to appease TS.
If you're struggling to properly type everything, you can start assigning any
to each of these interface properties, but you will forfeit strong type checking in the process.
Hope that helps!
I will leave this issue open with a view to potentially add these types to this project—but really they belong in Nuxt's repo, so I would perhaps open an issue there and reference this issue.
Hi, have raised a similar issue with nuxt specific fields of ComponentOptions
ref: https://cmty.app/nuxt/nuxt-class-component/issues/c8
I've left a working example using the directory structure suggested by @wagerfield above:
https://gist.github.com/stepbeekio/1d5392b13503dca248556f0457e83ffd
Copied below for those in a hurry:
import Vue from 'vue'
import { Store } from 'vuex'
// ComponentOptions is declared in types/options.d.ts
declare module 'vue/types/options' {
interface NuxtContext<V extends Vue> {
app: V,
isClient: boolean,
isServer: boolean,
isStatic: boolean,
isDev: boolean,
store: Store<any>, // Consider vuex-typex in future
env: object,
params: object,
query: object
}
interface ComponentOptions<V extends Vue> {
asyncData?(context: NuxtContext<V>): Promise<object> | object
fetch?(context: NuxtContext<V>): Promise<object> | object
}
}
nice, works for me ✨
Thanks @stepbeekio. I haven't abandoned this project—I'm patiently waiting for the release of Nuxt 2 so I can update the implementation to work with Webpack 4 and ts-loader
4.x which is much faster.
Note: I've added types for watchQuery
& key
on my end.
...
interface ComponentOptions<V extends Vue> {
asyncData?(context: NuxtContext<V>): Promise<object> | object
fetch?(context: NuxtContext<V>): Promise<object> | object
watchQuery?: string[]
key?: Function
}
...
@herkulano @hartmut-co-uk @stepbeekio I was thinking about just adding these declarations to this module rather than handing off the responsibility to Nuxt given that it's written in MJS and not TS. Will keep you updated.
@wagerfield I think adding to the module is a good idea. Keep me in touch :)
note added another line to ComponentOptions..
:
middleware?: string | string[]
@wagerfield I kind of took the lead on this around official Nuxt repo https://github.com/nuxt/nuxt.js/pull/4164.
Do like this:
@Component({
async asyncData({ params, error }) {
💀// impossible to use this.$http on @component 💀
const http = Vue.prototype.$nuxt.$http;
const objectGet = await http.get('/url')
const objectPost = await http.post('/url', { params })
return {
data1: objectGet.data,
data2: objectPost.data,
}
}
})
export default class NameOfYourClass extends Vue {
name: 'NameOfYourClass'
// AsyncData
data1?: type
data2?: type
[...]
}
Adding the asyncData property and using typescript without classes and decorators, throws this typing error:
Code:
Do you have any hints on solving this?