types: fix withDefaults type

This commit is contained in:
三咲智子 Kevin Deng 2023-07-21 00:18:45 +08:00
parent 623ba514ec
commit f703a11a43
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
2 changed files with 47 additions and 22 deletions

View File

@ -19,7 +19,7 @@ describe('defineProps w/ type declaration', () => {
const props = defineProps<{
foo: string
bool?: boolean
boolAndUndefined: boolean | undefined
boolOrUndefined: boolean | undefined
}>()
// explicitly declared type should be refined
expectType<string>(props.foo)
@ -27,7 +27,7 @@ describe('defineProps w/ type declaration', () => {
props.bar
expectType<boolean>(props.bool)
expectType<boolean>(props.boolAndUndefined)
expectType<boolean>(props.boolOrUndefined)
})
describe('defineProps w/ generics', () => {
@ -52,7 +52,8 @@ describe('defineProps w/ type declaration + withDefaults', () => {
y?: string
z?: string
bool?: boolean
boolAndUndefined: boolean | undefined
boolOrUndefined: boolean | undefined
defaultUndefined?: string
}>(),
{
number: 123,
@ -61,10 +62,14 @@ describe('defineProps w/ type declaration + withDefaults', () => {
fn: () => {},
genStr: () => '',
y: undefined,
z: 'string'
z: 'string',
defaultUndefined: undefined as string | undefined
}
)
// @ts-expect-error
res.number++
res.number + 1
res.arr.push('hi')
res.obj.x
@ -75,12 +80,21 @@ describe('defineProps w/ type declaration + withDefaults', () => {
// @ts-expect-error
res.y.slice()
expectType<string | undefined>(res.x)
expectType<string | undefined>(res.y)
expectType<string>(res.z)
expectType<boolean>(res.bool)
expectType<boolean>(res.boolAndUndefined)
type T = {
number: number
arr: string[]
obj: { x: number }
fn: (e: string) => void
genStr: string
x: string | undefined
y: string | undefined
z: string
bool: boolean
boolOrUndefined: boolean
defaultUndefined: string | undefined
}
expectType<T>(res)
expectType<typeof res>({} as T)
})
describe('defineProps w/ union type declaration + withDefaults', () => {
@ -127,6 +141,9 @@ describe('defineProps w/ generic type declaration + withDefaults', <T extends
res.n + 1
// @ts-expect-error readonly
res.n++
expectType<T[] | { x: T }>(res.generic1)
expectType<{ x: T }>(res.generic2)
expectType<TString>(res.generic3)

View File

@ -293,23 +293,31 @@ type InferDefault<P, T> =
| ((props: P) => T & {})
| (T extends NativeType ? T : never)
type NonPartial<T> = {
[K in keyof Required<T>]: T[K]
}
type UndefinedDefault<T, Default> = Default extends undefined
? T
: NotUndefined<T>
type PropsWithDefaults<
T,
Defaults extends InferDefaults<T>,
BKeys extends keyof T
> = Omit<T, keyof Defaults> & {
[K in keyof Defaults]-?: K extends keyof T
? Defaults[K] extends undefined
? T[K]
: NotUndefined<T[K]>
: never
} & {
readonly [K in BKeys]-?: K extends keyof Defaults
? Defaults[K] extends undefined
? boolean | undefined
> = Readonly<
NonPartial<Omit<T, keyof (Defaults | BKeys)>> & {
[K in keyof Defaults]-?: K extends keyof T
? UndefinedDefault<T[K], Defaults[K]>
: never
} & {
[K in BKeys]: K extends keyof Defaults
? Defaults[K] extends undefined
? boolean | undefined
: boolean
: boolean
: boolean
}
}
>
/**
* Vue `<script setup>` compiler macro for providing props default values when