Skip to content

Commit

Permalink
feat(types): add asyncData return types to component instance type (#…
Browse files Browse the repository at this point in the history
…9239)

Co-authored-by: Daniel Roe <daniel@roe.dev>
  • Loading branch information
carbotaniuman and danielroe committed Jun 2, 2021
1 parent a57ac94 commit e8281dd
Showing 1 changed file with 96 additions and 3 deletions.
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>
}
}

0 comments on commit e8281dd

Please sign in to comment.