]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): ensure defineProps with generics return correct types
authorEvan You <yyx990803@gmail.com>
Sun, 26 Mar 2023 07:58:04 +0000 (15:58 +0800)
committerEvan You <yyx990803@gmail.com>
Sun, 26 Mar 2023 07:58:04 +0000 (15:58 +0800)
packages/dts-test/setupHelpers.test-d.ts
packages/runtime-core/src/apiSetupHelpers.ts

index 8ad085f9bce5dabb1475836db4fe7f326de27626..a3ab02cab9779a3bf2fd7f12e0a5417ed99429ad 100644 (file)
@@ -24,6 +24,16 @@ describe('defineProps w/ type declaration', () => {
   expectType<boolean>(props.boolAndUndefined)
 })
 
+describe('defineProps w/ generics', () => {
+  function test<T extends boolean>() {
+    const props = defineProps<{ foo: T; bar: string; x?: boolean }>()
+    expectType<T>(props.foo)
+    expectType<string>(props.bar)
+    expectType<boolean>(props.x)
+  }
+  test()
+})
+
 describe('defineProps w/ type declaration + withDefaults', () => {
   const res = withDefaults(
     defineProps<{
index 882e0389c97c6473f2a5fb86e2257d5675761adc..71ac1191a314ebd2893260325700934d8fca8d52 100644 (file)
@@ -61,15 +61,7 @@ export function defineProps<
   PP extends ComponentObjectPropsOptions = ComponentObjectPropsOptions
 >(props: PP): Prettify<Readonly<ExtractPropTypes<PP>>>
 // overload 3: typed-based declaration
-export function defineProps<TypeProps>(): Prettify<
-  Readonly<
-    Omit<TypeProps, BooleanKey<TypeProps>> & {
-      [K in keyof Pick<TypeProps, BooleanKey<TypeProps>>]-?: NotUndefined<
-        TypeProps[K]
-      >
-    }
-  >
->
+export function defineProps<TypeProps>(): ResolveProps<TypeProps>
 // implementation
 export function defineProps() {
   if (__DEV__) {
@@ -78,6 +70,20 @@ export function defineProps() {
   return null as any
 }
 
+type ResolveProps<T, BooleanKeys extends keyof T = BooleanKey<T>> = Prettify<
+  Readonly<
+    T & {
+      [K in BooleanKeys]-?: boolean
+    }
+  >
+>
+
+type BooleanKey<T, K extends keyof T = keyof T> = K extends any
+  ? [T[K]] extends [boolean | undefined]
+    ? K
+    : never
+  : never
+
 /**
  * Vue `<script setup>` compiler macro for declaring a component's emitted
  * events. The expected argument is the same as the component `emits` option.
@@ -139,12 +145,6 @@ export function defineExpose<
 
 type NotUndefined<T> = T extends undefined ? never : T
 
-type BooleanKey<T, K extends keyof T = keyof T> = K extends any
-  ? [T[K]] extends [boolean | undefined]
-    ? K
-    : never
-  : never
-
 type InferDefaults<T> = {
   [K in keyof T]?: InferDefault<T, NotUndefined<T[K]>>
 }