feat(types): add `asyncData` return types to component instance type (#9239)

Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
carbotaniuman 2021-06-02 08:32:39 -05:00 committed by GitHub
parent a57ac94420
commit e8281dded7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 96 additions and 3 deletions

View File

@ -5,14 +5,32 @@
import Vue from 'vue'
import { MetaInfo } from 'vue-meta'
import { Route } from 'vue-router'
import { RecordPropsDefinition, PropsDefinition, ComponentOptions } from 'vue/types/options'
import { CombinedVueInstance, ExtendedVue } from 'vue/types/vue'
import { NuxtRuntimeConfig } from '../config/runtime'
import { Context, Middleware, Transition, NuxtApp } from './index'
// https://github.com/vuejs/vue/blob/dev/types/options.d.ts#L63-L66
type DefaultData<V> = object | ((this: V) => object)
type DefaultProps = Record<string, any>
type DefaultMethods<V> = { [key: string]: (this: V, ...args: any[]) => any }
type DefaultComputed = { [key: string]: any }
type DefaultAsyncData<V> = ((this: V, context: Context) => Promise<object | void> | object | void)
declare module 'vue/types/options' {
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
interface ComponentOptions<V extends Vue> {
interface ComponentOptions<
V extends Vue,
/* eslint-disable no-unused-vars,@typescript-eslint/no-unused-vars */
Data = DefaultData<V>,
Methods = DefaultMethods<V>,
Computed = DefaultComputed,
PropsDef = PropsDefinition<DefaultProps>,
Props = DefaultProps,
/* eslint-enable no-unused-vars,@typescript-eslint/no-unused-vars */
AsyncData = DefaultAsyncData<V>
> {
// eslint-disable-next-line @typescript-eslint/ban-types
asyncData?(ctx: Context): Promise<object | void> | object | void
asyncData?: AsyncData
fetch?(ctx: Context): Promise<void> | void
fetchKey?: string | ((getKey: (id: string) => number) => string)
fetchDelay?: number
@ -30,6 +48,59 @@ declare module 'vue/types/options' {
}
}
type DataDef<Data, Props, V> = Data | ((this: Readonly<Props> & V) => Data)
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T
type Merged<Data, AsyncData> = {
[key in keyof Data | keyof AsyncData]: key extends keyof Data ? key extends keyof AsyncData ? NonNullable<Data[key]> | AsyncData[key] : Data[key] : key extends keyof AsyncData ? AsyncData[key] : never
}
type ThisTypedComponentOptionsWithArrayPropsAndAsyncData<
V extends Vue,
Data,
Methods,
Computed,
PropNames extends string,
AsyncData
> = object &
ComponentOptions<
V,
DataDef<Data, Record<PropNames, any>, V>,
Methods,
Computed,
PropNames[],
Record<PropNames, any>,
DataDef<AsyncData, PropNames, V>
> &
ThisType<
CombinedVueInstance<
V,
Merged<Data, Awaited<AsyncData>>,
Methods,
Computed,
Readonly<Record<PropNames, any>>
>
>
export type ThisTypedComponentOptionsWithRecordPropsAndAsyncData<
V extends Vue,
Data,
Methods,
Computed,
Props,
AsyncData
> = object &
ComponentOptions<
V,
DataDef<Data, Props, V>,
Methods,
Computed,
RecordPropsDefinition<Props>,
Props,
DataDef<AsyncData, Props, V>
> &
ThisType<
CombinedVueInstance<V, Merged<Data, Awaited<AsyncData>>, Methods, Computed, Readonly<Props>>
>
declare module 'vue/types/vue' {
interface Vue {
$config: NuxtRuntimeConfig
@ -41,4 +112,26 @@ declare module 'vue/types/vue' {
timestamp: number
}
}
interface VueConstructor<V extends Vue> {
extend<Data, Methods, Computed, PropNames extends string, AsyncData>(
options?: ThisTypedComponentOptionsWithArrayPropsAndAsyncData<
V,
Data,
Methods,
Computed,
PropNames,
AsyncData
>
): ExtendedVue<V, Data, Methods, Computed, Record<PropNames, any>>
extend<Data, Methods, Computed, Props, AsyncData>(
options?: ThisTypedComponentOptionsWithRecordPropsAndAsyncData<
V,
Data,
Methods,
Computed,
Props,
AsyncData
>
): ExtendedVue<V, Data, Methods, Computed, Props>
}
}