]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): retain union type narrowing with defaults applied (#12108)
authoredison <daiwei521@126.com>
Fri, 11 Oct 2024 03:17:15 +0000 (11:17 +0800)
committerEvan You <evan@vuejs.org>
Fri, 11 Oct 2024 03:17:48 +0000 (11:17 +0800)
close #12106

packages-private/dts-test/setupHelpers.test-d.ts
packages/runtime-core/src/apiSetupHelpers.ts

index 4074176ff982e819fb6d3ebeb71e20a50557d153..7b5d6f147f08ab5cc3a8c8b58995af255741df32 100644 (file)
@@ -240,6 +240,23 @@ describe('withDefaults w/ defineProp type is different from the defaults type',
   res1.value
 })
 
+describe('withDefaults w/ defineProp discriminate union type', () => {
+  const props = withDefaults(
+    defineProps<
+      { type: 'button'; buttonType?: 'submit' } | { type: 'link'; href: string }
+    >(),
+    {
+      type: 'button',
+    },
+  )
+  if (props.type === 'button') {
+    expectType<'submit' | undefined>(props.buttonType)
+  }
+  if (props.type === 'link') {
+    expectType<string>(props.href)
+  }
+})
+
 describe('defineProps w/ runtime declaration', () => {
   // runtime declaration
   const props = defineProps({
index 33817818a9310ff747e48cda86494ab6aa30359b..54712c6807a606f05daa729c7c56bf52623d31dd 100644 (file)
@@ -331,21 +331,23 @@ type PropsWithDefaults<
   T,
   Defaults extends InferDefaults<T>,
   BKeys extends keyof T,
-> = Readonly<MappedOmit<T, keyof Defaults>> & {
-  readonly [K in keyof Defaults as K extends keyof T
-    ? K
-    : never]-?: K extends keyof T
-    ? Defaults[K] extends undefined
-      ? IfAny<Defaults[K], NotUndefined<T[K]>, T[K]>
-      : NotUndefined<T[K]>
-    : never
-} & {
-  readonly [K in BKeys]-?: K extends keyof Defaults
-    ? Defaults[K] extends undefined
-      ? boolean | undefined
-      : boolean
-    : boolean
-}
+> = T extends unknown
+  ? Readonly<MappedOmit<T, keyof Defaults>> & {
+      readonly [K in keyof Defaults as K extends keyof T
+        ? K
+        : never]-?: K extends keyof T
+        ? Defaults[K] extends undefined
+          ? IfAny<Defaults[K], NotUndefined<T[K]>, T[K]>
+          : NotUndefined<T[K]>
+        : never
+    } & {
+      readonly [K in BKeys]-?: K extends keyof Defaults
+        ? Defaults[K] extends undefined
+          ? boolean | undefined
+          : boolean
+        : boolean
+    }
+  : never
 
 /**
  * Vue `<script setup>` compiler macro for providing props default values when