Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from Jun 2, 2021
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
99 changes: 96 additions & 3 deletions packages/types/app/vue.d.ts
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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>
}
}