Skip to content

Commit

Permalink
types(defineProps): remove optional properties from type
Browse files Browse the repository at this point in the history
  • Loading branch information
pikax committed Aug 7, 2022
1 parent a95554d commit 43065b5
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
9 changes: 8 additions & 1 deletion packages/runtime-core/src/apiSetupHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,14 @@ export function defineProps<
PP extends ComponentObjectPropsOptions = ComponentObjectPropsOptions
>(props: PP): Readonly<ExtractPropTypes<PP>>
// overload 3: typed-based declaration
export function defineProps<TypeProps>(): Readonly<TypeProps>
export function defineProps<T>(): T extends object
? {
// use needed to remove the optional property
[K in keyof Required<T>]: K extends OptionalPropertyOf<T>
? T[K] | undefined
: T[K]
}
: Readonly<T>
// implementation
export function defineProps() {
if (__DEV__) {
Expand Down
9 changes: 9 additions & 0 deletions packages/shared/src/typeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,12 @@ export type LooseRequired<T> = { [P in string & keyof T]: T[P] }
// If the the type T accepts type "any", output type Y, otherwise output type N.
// https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360
export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N

// Extract optional properties from a type
// https://stackoverflow.com/a/53899815
export type OptionalPropertyOf<T extends object> = Exclude<
{
[K in keyof T]: T extends Record<K, T[K]> ? never : K
}[keyof T],
undefined
>
6 changes: 6 additions & 0 deletions test-dts/setupHelpers.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@ describe('defineProps w/ type declaration', () => {
// type declaration
const props = defineProps<{
foo: string
x?: string
}>()
// explicitly declared type should be refined
expectType<string>(props.foo)

// force check the actual type doing expectType<string|undefined>(props.x) does not
// error when is not undefined, this way it does
// #6420
expectType<typeof props['x']>({} as unknown as string | undefined)
// @ts-expect-error
props.bar
})
Expand Down

0 comments on commit 43065b5

Please sign in to comment.