Skip to content

Commit

Permalink
fix(types): ensure defineProps with generics return correct types
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Mar 26, 2023
1 parent f61499d commit c288c7b
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 15 deletions.
10 changes: 10 additions & 0 deletions packages/dts-test/setupHelpers.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<{
Expand Down
30 changes: 15 additions & 15 deletions packages/runtime-core/src/apiSetupHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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__) {
Expand All @@ -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.
Expand Down Expand Up @@ -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]>>
}
Expand Down

0 comments on commit c288c7b

Please sign in to comment.