From 051c5669665bf44d4b9fa527dc5309b76e17b836 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 16 May 2023 13:52:26 +0100 Subject: [PATCH] types(withDefaults): Allow to be used with generic defineProps --- packages/dts-test/setupHelpers.test-d.ts | 34 +++++++++++++ packages/runtime-core/src/apiSetupHelpers.ts | 52 +++++++++++--------- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/packages/dts-test/setupHelpers.test-d.ts b/packages/dts-test/setupHelpers.test-d.ts index 9b68b345268..77342590dc6 100644 --- a/packages/dts-test/setupHelpers.test-d.ts +++ b/packages/dts-test/setupHelpers.test-d.ts @@ -100,6 +100,40 @@ describe('defineProps w/ union type declaration + withDefaults', () => { ) }) +describe('defineProps w/ generic type declaration + withDefaults', () => { + const res = withDefaults( + defineProps<{ + n?: number + bool?: boolean + + generic1?: T[] | { x: T } + generic2?: { x: T } + generic3?: TString + generic4?: TA + }>(), + { + n: 123, + + generic1: () => [123, 33] as T[], + generic2: () => ({ x: 123 } as { x: T }), + + generic3: () => 'test' as TString, + generic4: () => ({ a: 'test' } as TA) + } + ) + + res.n + 1 + + expectType(res.generic1) + expectType<{ x: T }>(res.generic2) + expectType(res.generic3) + expectType(res.generic4) + + expectType(res.bool) +}) + describe('defineProps w/ runtime declaration', () => { // runtime declaration const props = defineProps({ diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts index 3ad330a1c27..76ad08cf63a 100644 --- a/packages/runtime-core/src/apiSetupHelpers.ts +++ b/packages/runtime-core/src/apiSetupHelpers.ts @@ -81,7 +81,10 @@ export function defineProps< PP extends ComponentObjectPropsOptions = ComponentObjectPropsOptions >(props: PP): Prettify>> // overload 3: typed-based declaration -export function defineProps(): DefineProps +export function defineProps(): DefineProps< + TypeProps, + BooleanKey +> // implementation export function defineProps() { if (__DEV__) { @@ -90,8 +93,8 @@ export function defineProps() { return null as any } -type DefineProps = Readonly & { - readonly [K in BooleanKey]-?: boolean +type DefineProps = Readonly & { + readonly [K in BKeys]-?: boolean } type BooleanKey = K extends any @@ -281,26 +284,27 @@ interface DefineModelOptions { type NotUndefined = T extends undefined ? never : T type InferDefaults = { - [K in keyof T]?: InferDefault> + [K in keyof T]?: InferDefault } -type InferDefault = T extends - | null - | number - | string - | boolean - | symbol - | Function - ? T | ((props: P) => T) - : (props: P) => T - -type PropsWithDefaults = Base & { - [K in keyof Defaults]: K extends keyof Base +type NativeType = null | number | string | boolean | symbol | Function + +type InferDefault = + | ((props: P) => T & {}) + | (T extends NativeType ? T : never) + +type PropsWithDefaults< + T, + Defaults extends InferDefaults, + BKeys extends keyof T +> = Omit & { + [K in keyof Defaults]-?: K extends keyof T ? Defaults[K] extends undefined - ? Base[K] - : NotUndefined + ? T[K] + : NotUndefined : never -} +} & { readonly [K in BKeys]-?: boolean } + /** * Vue `