feat(types): provide ExtractPublicPropTypes utility type

ref #5272
close #8168
This commit is contained in:
Evan You 2023-05-02 11:06:24 +08:00
parent 918ec8a5cb
commit bff63c5498
5 changed files with 65 additions and 3 deletions

View File

@ -162,7 +162,8 @@ function innerResolveTypeElements(
case 'TSTypeReference': { case 'TSTypeReference': {
const typeName = getReferenceName(node) const typeName = getReferenceName(node)
if ( if (
typeName === 'ExtractPropTypes' && (typeName === 'ExtractPropTypes' ||
typeName === 'ExtractPublicPropTypes') &&
node.typeParameters && node.typeParameters &&
scope.imports[typeName]?.source === 'vue' scope.imports[typeName]?.source === 'vue'
) { ) {

View File

@ -0,0 +1,30 @@
import { ExtractPropTypes, ExtractPublicPropTypes } from 'vue'
import { expectType, Prettify } from './utils'
const propsOptions = {
foo: {
default: 1
},
bar: {
type: String,
required: true
},
baz: Boolean,
qux: Array
} as const
// internal facing props
declare const props: Prettify<ExtractPropTypes<typeof propsOptions>>
expectType<number>(props.foo)
expectType<string>(props.bar)
expectType<boolean>(props.baz)
expectType<unknown[] | undefined>(props.qux)
// external facing props
declare const publicProps: Prettify<ExtractPublicPropTypes<typeof propsOptions>>
expectType<number | undefined>(publicProps.foo)
expectType<string>(publicProps.bar)
expectType<boolean | undefined>(publicProps.baz)
expectType<unknown[] | undefined>(publicProps.qux)

View File

@ -17,3 +17,5 @@ export type IsUnion<T, U extends T = T> = (
: true : true
export type IsAny<T> = 0 extends 1 & T ? true : false export type IsAny<T> = 0 extends 1 & T ? true : false
export type Prettify<T> = { [K in keyof T]: T[K] } & {}

View File

@ -128,14 +128,42 @@ type InferPropType<T> = [T] extends [null]
: V : V
: T : T
/**
* Extract prop types from a runtime props options object.
* The extracted types are **internal** - i.e. the resolved props received by
* the component.
* - Boolean props are always present
* - Props with default values are always present
*
* To extract accepted props from the parent, use {@link ExtractPublicPropTypes}.
*/
export type ExtractPropTypes<O> = { export type ExtractPropTypes<O> = {
// use `keyof Pick<O, RequiredKeys<O>>` instead of `RequiredKeys<O>` to support IDE features // use `keyof Pick<O, RequiredKeys<O>>` instead of `RequiredKeys<O>` to
// support IDE features
[K in keyof Pick<O, RequiredKeys<O>>]: InferPropType<O[K]> [K in keyof Pick<O, RequiredKeys<O>>]: InferPropType<O[K]>
} & { } & {
// use `keyof Pick<O, OptionalKeys<O>>` instead of `OptionalKeys<O>` to support IDE features // use `keyof Pick<O, OptionalKeys<O>>` instead of `OptionalKeys<O>` to
// support IDE features
[K in keyof Pick<O, OptionalKeys<O>>]?: InferPropType<O[K]> [K in keyof Pick<O, OptionalKeys<O>>]?: InferPropType<O[K]>
} }
type PublicRequiredKeys<T> = {
[K in keyof T]: T[K] extends { required: true } ? K : never
}[keyof T]
type PublicOptionalKeys<T> = Exclude<keyof T, PublicRequiredKeys<T>>
/**
* Extract prop types from a runtime props options object.
* The extracted types are **public** - i.e. the expected props that can be
* passed to component.
*/
export type ExtractPublicPropTypes<O> = {
[K in keyof Pick<O, PublicRequiredKeys<O>>]: InferPropType<O[K]>
} & {
[K in keyof Pick<O, PublicOptionalKeys<O>>]?: InferPropType<O[K]>
}
const enum BooleanFlags { const enum BooleanFlags {
shouldCast, shouldCast,
shouldCastTrue shouldCastTrue

View File

@ -254,6 +254,7 @@ export type {
ComponentPropsOptions, ComponentPropsOptions,
ComponentObjectPropsOptions, ComponentObjectPropsOptions,
ExtractPropTypes, ExtractPropTypes,
ExtractPublicPropTypes,
ExtractDefaultPropTypes ExtractDefaultPropTypes
} from './componentProps' } from './componentProps'
export type { export type {