Просмотр исходного кода

fix(types): ensure defineProps with generics return correct types

Evan You 3 лет назад
Родитель
Сommit
c288c7b0bd
2 измененных файлов с 25 добавлено и 15 удалено
  1. 10 0
      packages/dts-test/setupHelpers.test-d.ts
  2. 15 15
      packages/runtime-core/src/apiSetupHelpers.ts

+ 10 - 0
packages/dts-test/setupHelpers.test-d.ts

@@ -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<{

+ 15 - 15
packages/runtime-core/src/apiSetupHelpers.ts

@@ -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]>>
 }