Skip to content

Commit

Permalink
fix(types/tsx): optional props from Mixin/Extends are treated as requ…
Browse files Browse the repository at this point in the history
…ired (#2048)
  • Loading branch information
wonderful-panda authored Sep 16, 2020
1 parent 7e68ddd commit 89e9ab8
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 46 deletions.
23 changes: 15 additions & 8 deletions packages/runtime-core/src/apiDefineComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import {
AllowedComponentProps,
ComponentCustomProps
} from './component'
import { ExtractPropTypes, ComponentPropsOptions } from './componentProps'
import {
ExtractPropTypes,
ComponentPropsOptions,
ExtractDefaultPropTypes
} from './componentProps'
import { EmitsOptions } from './componentEmits'
import { isFunction } from '@vue/shared'
import { VNodeProps } from './vnode'
Expand All @@ -37,32 +41,35 @@ export type DefineComponent<
E extends EmitsOptions = Record<string, any>,
EE extends string = string,
PP = PublicProps,
RequiredProps = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
OptionalProps = Readonly<ExtractPropTypes<PropsOrPropOptions, false>>
Props = Readonly<ExtractPropTypes<PropsOrPropOptions>>,
Defaults = ExtractDefaultPropTypes<PropsOrPropOptions>
> = ComponentPublicInstanceConstructor<
CreateComponentPublicInstance<
OptionalProps,
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
PP & OptionalProps
PP & Props,
Defaults,
true
> &
RequiredProps
Props
> &
ComponentOptionsBase<
RequiredProps,
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE
EE,
Defaults
> &
PP

Expand Down
72 changes: 61 additions & 11 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ import {
WritableComputedOptions,
toRaw
} from '@vue/reactivity'
import { ComponentObjectPropsOptions, ExtractPropTypes } from './componentProps'
import {
ComponentObjectPropsOptions,
ExtractPropTypes,
ExtractDefaultPropTypes
} from './componentProps'
import { EmitsOptions } from './componentEmits'
import { Directive } from './directives'
import {
Expand Down Expand Up @@ -81,7 +85,8 @@ export interface ComponentOptionsBase<
Mixin extends ComponentOptionsMixin,
Extends extends ComponentOptionsMixin,
E extends EmitsOptions,
EE extends string = string
EE extends string = string,
Defaults = {}
>
extends LegacyOptions<Props, D, C, M, Mixin, Extends>,
ComponentInternalOptions,
Expand Down Expand Up @@ -148,6 +153,8 @@ export interface ComponentOptionsBase<
__isFragment?: never
__isTeleport?: never
__isSuspense?: never

__defaults?: Defaults
}

export type ComponentOptionsWithoutProps<
Expand All @@ -159,8 +166,20 @@ export type ComponentOptionsWithoutProps<
Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
EE extends string = string
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
EE extends string = string,
Defaults = {}
> = ComponentOptionsBase<
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
Defaults
> & {
props?: undefined
} & ThisType<
CreateComponentPublicInstance<
Expand All @@ -172,7 +191,9 @@ export type ComponentOptionsWithoutProps<
Mixin,
Extends,
E,
Readonly<Props>
Readonly<Props>,
Defaults,
false
>
>

Expand All @@ -187,7 +208,18 @@ export type ComponentOptionsWithArrayProps<
E extends EmitsOptions = EmitsOptions,
EE extends string = string,
Props = Readonly<{ [key in PropNames]?: any }>
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
> = ComponentOptionsBase<
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
{}
> & {
props: PropNames[]
} & ThisType<
CreateComponentPublicInstance<
Expand All @@ -212,8 +244,20 @@ export type ComponentOptionsWithObjectProps<
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = EmitsOptions,
EE extends string = string,
Props = Readonly<ExtractPropTypes<PropsOptions>>
> = ComponentOptionsBase<Props, RawBindings, D, C, M, Mixin, Extends, E, EE> & {
Props = Readonly<ExtractPropTypes<PropsOptions>>,
Defaults = ExtractDefaultPropTypes<PropsOptions>
> = ComponentOptionsBase<
Props,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
Defaults
> & {
props: PropsOptions & ThisType<void>
} & ThisType<
CreateComponentPublicInstance<
Expand All @@ -224,7 +268,10 @@ export type ComponentOptionsWithObjectProps<
M,
Mixin,
Extends,
E
E,
Props,
Defaults,
false
>
>

Expand Down Expand Up @@ -261,6 +308,7 @@ export type ComponentOptionsMixin = ComponentOptionsBase<
any,
any,
any,
any,
any
>

Expand Down Expand Up @@ -347,20 +395,22 @@ interface LegacyOptions<
delimiters?: [string, string]
}

export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M'
export type OptionTypesKeys = 'P' | 'B' | 'D' | 'C' | 'M' | 'Defaults'

export type OptionTypesType<
P = {},
B = {},
D = {},
C extends ComputedOptions = {},
M extends MethodOptions = {}
M extends MethodOptions = {},
Defaults = {}
> = {
P: P
B: B
D: D
C: C
M: M
Defaults: Defaults
}

const enum OptionTypes {
Expand Down
31 changes: 15 additions & 16 deletions packages/runtime-core/src/componentProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,15 @@ type PropMethod<T, TConstructor = any> = T extends (...args: any) => any // if i
? { new (): TConstructor; (): T; readonly prototype: TConstructor } // Create Function like constructor
: never

type RequiredKeys<T, MakeDefaultRequired> = {
[K in keyof T]: T[K] extends
| { required: true }
| (MakeDefaultRequired extends true ? { default: any } : never)
? K
: never
type RequiredKeys<T> = {
[K in keyof T]: T[K] extends { required: true } | { default: any } ? K : never
}[keyof T]

type OptionalKeys<T, MakeDefaultRequired> = Exclude<
keyof T,
RequiredKeys<T, MakeDefaultRequired>
>
type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>

type DefaultKeys<T> = {
[K in keyof T]: T[K] extends { default: any } ? K : never
}[keyof T]

type InferPropType<T> = T extends null
? any // null & true would fail to infer
Expand All @@ -86,19 +83,21 @@ type InferPropType<T> = T extends null
? boolean
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T

export type ExtractPropTypes<
O,
MakeDefaultRequired extends boolean = true
> = O extends object
? { [K in RequiredKeys<O, MakeDefaultRequired>]: InferPropType<O[K]> } &
{ [K in OptionalKeys<O, MakeDefaultRequired>]?: InferPropType<O[K]> }
export type ExtractPropTypes<O> = O extends object
? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
{ [K in OptionalKeys<O>]?: InferPropType<O[K]> }
: { [K in string]: any }

const enum BooleanFlags {
shouldCast,
shouldCastTrue
}

// extract props which defined with default from prop options
export type ExtractDefaultPropTypes<O> = O extends object
? { [K in DefaultKeys<O>]: InferPropType<O[K]> }
: {}

type NormalizedProp =
| null
| (PropOptions & {
Expand Down
24 changes: 18 additions & 6 deletions packages/runtime-core/src/componentPublicInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,11 @@ type MixinToOptionTypes<T> = T extends ComponentOptionsBase<
infer M,
infer Mixin,
infer Extends,
any
any,
any,
infer Defaults
>
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}> &
? OptionTypesType<P & {}, B & {}, D & {}, C & {}, M & {}, Defaults & {}> &
IntersectionMixin<Mixin> &
IntersectionMixin<Extends>
: never
Expand Down Expand Up @@ -130,14 +132,18 @@ export type CreateComponentPublicInstance<
Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
E extends EmitsOptions = {},
PublicProps = P,
Defaults = {},
MakeDefaultsOptional extends boolean = false,
PublicMixin = IntersectionMixin<Mixin> & IntersectionMixin<Extends>,
PublicP = UnwrapMixinsType<PublicMixin, 'P'> & EnsureNonVoid<P>,
PublicB = UnwrapMixinsType<PublicMixin, 'B'> & EnsureNonVoid<B>,
PublicD = UnwrapMixinsType<PublicMixin, 'D'> & EnsureNonVoid<D>,
PublicC extends ComputedOptions = UnwrapMixinsType<PublicMixin, 'C'> &
EnsureNonVoid<C>,
PublicM extends MethodOptions = UnwrapMixinsType<PublicMixin, 'M'> &
EnsureNonVoid<M>
EnsureNonVoid<M>,
PublicDefaults = UnwrapMixinsType<PublicMixin, 'Defaults'> &
EnsureNonVoid<Defaults>
> = ComponentPublicInstance<
PublicP,
PublicB,
Expand All @@ -146,7 +152,9 @@ export type CreateComponentPublicInstance<
PublicM,
E,
PublicProps,
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E>
PublicDefaults,
MakeDefaultsOptional,
ComponentOptionsBase<P, B, D, C, M, Mixin, Extends, E, string, Defaults>
>

// public properties exposed on the proxy, which is used as the render context
Expand All @@ -159,11 +167,15 @@ export type ComponentPublicInstance<
M extends MethodOptions = {},
E extends EmitsOptions = {},
PublicProps = P,
Options = ComponentOptionsBase<any, any, any, any, any, any, any, any>
Defaults = {},
MakeDefaultsOptional extends boolean = false,
Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>
> = {
$: ComponentInternalInstance
$data: D
$props: P & PublicProps
$props: MakeDefaultsOptional extends true
? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
: P & PublicProps
$attrs: Data
$refs: Data
$slots: Slots
Expand Down
6 changes: 4 additions & 2 deletions packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export {
} from './apiLifecycle'
export { provide, inject } from './apiInject'
export { nextTick } from './scheduler'
export { defineComponent, DefineComponent } from './apiDefineComponent'
export { defineComponent } from './apiDefineComponent'
export { defineAsyncComponent } from './apiAsyncComponent'

// Advanced API ----------------------------------------------------------------
Expand Down Expand Up @@ -166,6 +166,7 @@ export {
ComponentCustomProps,
AllowedComponentProps
} from './component'
export { DefineComponent } from './apiDefineComponent'
export {
ComponentOptions,
ComponentOptionsMixin,
Expand Down Expand Up @@ -198,7 +199,8 @@ export {
PropType,
ComponentPropsOptions,
ComponentObjectPropsOptions,
ExtractPropTypes
ExtractPropTypes,
ExtractDefaultPropTypes
} from './componentProps'
export {
Directive,
Expand Down
Loading

0 comments on commit 89e9ab8

Please sign in to comment.