Просмотр исходного кода

feat(types): provide ExtractPublicPropTypes utility type

ref #5272
close #8168
Evan You 3 лет назад
Родитель
Сommit
bff63c5498

+ 2 - 1
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'
       ) {

+ 30 - 0
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<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)

+ 2 - 0
packages/dts-test/utils.d.ts

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

+ 30 - 2
packages/runtime-core/src/componentProps.ts

@@ -128,14 +128,42 @@ type InferPropType<T> = [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<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]>
 } & {
-  // 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]>
 }
 
+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 {
   shouldCast,
   shouldCastTrue

+ 1 - 0
packages/runtime-core/src/index.ts

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