From bff63c5498f5fa098689c18defe48ae08d47eadb Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 2 May 2023 11:06:24 +0800 Subject: [PATCH] feat(types): provide ExtractPublicPropTypes utility type ref #5272 close #8168 --- .../compiler-sfc/src/script/resolveType.ts | 3 +- packages/dts-test/extractProps.test-d.ts | 30 +++++++++++++++++ packages/dts-test/utils.d.ts | 2 ++ packages/runtime-core/src/componentProps.ts | 32 +++++++++++++++++-- packages/runtime-core/src/index.ts | 1 + 5 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 packages/dts-test/extractProps.test-d.ts diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index bf29ae089bd..2fa8d028c65 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -162,7 +162,8 @@ function innerResolveTypeElements( case 'TSTypeReference': { const typeName = getReferenceName(node) if ( - typeName === 'ExtractPropTypes' && + (typeName === 'ExtractPropTypes' || + typeName === 'ExtractPublicPropTypes') && node.typeParameters && scope.imports[typeName]?.source === 'vue' ) { diff --git a/packages/dts-test/extractProps.test-d.ts b/packages/dts-test/extractProps.test-d.ts new file mode 100644 index 00000000000..a40a15ef383 --- /dev/null +++ b/packages/dts-test/extractProps.test-d.ts @@ -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> + +expectType(props.foo) +expectType(props.bar) +expectType(props.baz) +expectType(props.qux) + +// external facing props +declare const publicProps: Prettify> + +expectType(publicProps.foo) +expectType(publicProps.bar) +expectType(publicProps.baz) +expectType(publicProps.qux) diff --git a/packages/dts-test/utils.d.ts b/packages/dts-test/utils.d.ts index 790098d962d..c478b30cb6f 100644 --- a/packages/dts-test/utils.d.ts +++ b/packages/dts-test/utils.d.ts @@ -17,3 +17,5 @@ export type IsUnion = ( : true export type IsAny = 0 extends 1 & T ? true : false + +export type Prettify = { [K in keyof T]: T[K] } & {} diff --git a/packages/runtime-core/src/componentProps.ts b/packages/runtime-core/src/componentProps.ts index 887ce4f39c6..4d402789555 100644 --- a/packages/runtime-core/src/componentProps.ts +++ b/packages/runtime-core/src/componentProps.ts @@ -128,14 +128,42 @@ type InferPropType = [T] extends [null] : V : 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 = { - // use `keyof Pick>` instead of `RequiredKeys` to support IDE features + // use `keyof Pick>` instead of `RequiredKeys` to + // support IDE features [K in keyof Pick>]: InferPropType } & { - // use `keyof Pick>` instead of `OptionalKeys` to support IDE features + // use `keyof Pick>` instead of `OptionalKeys` to + // support IDE features [K in keyof Pick>]?: InferPropType } +type PublicRequiredKeys = { + [K in keyof T]: T[K] extends { required: true } ? K : never +}[keyof T] + +type PublicOptionalKeys = Exclude> + +/** + * 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 = { + [K in keyof Pick>]: InferPropType +} & { + [K in keyof Pick>]?: InferPropType +} + const enum BooleanFlags { shouldCast, shouldCastTrue diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index a115b0179c1..0d5fc39d5f6 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -254,6 +254,7 @@ export type { ComponentPropsOptions, ComponentObjectPropsOptions, ExtractPropTypes, + ExtractPublicPropTypes, ExtractDefaultPropTypes } from './componentProps' export type {