parent
41e02f0fac
commit
3755e60c52
@ -60,7 +60,7 @@ type PropConstructor<T = any> =
|
|||||||
| { (): T }
|
| { (): T }
|
||||||
| PropMethod<T>
|
| PropMethod<T>
|
||||||
|
|
||||||
type PropMethod<T, TConstructor = any> = T extends (...args: any) => any // if is function with args
|
type PropMethod<T, TConstructor = any> = [T] extends [(...args: any) => any] // if is function with args
|
||||||
? { new (): TConstructor; (): T; readonly prototype: TConstructor } // Create Function like constructor
|
? { new (): TConstructor; (): T; readonly prototype: TConstructor } // Create Function like constructor
|
||||||
: never
|
: never
|
||||||
|
|
||||||
@ -89,17 +89,19 @@ type DefaultKeys<T> = {
|
|||||||
: never
|
: never
|
||||||
}[keyof T]
|
}[keyof T]
|
||||||
|
|
||||||
type InferPropType<T> = T extends null
|
type InferPropType<T> = [T] extends [null]
|
||||||
? any // null & true would fail to infer
|
? any // null & true would fail to infer
|
||||||
: T extends { type: null | true }
|
: [T] extends [{ type: null | true }]
|
||||||
? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
|
? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
|
||||||
: T extends ObjectConstructor | { type: ObjectConstructor }
|
: [T] extends [ObjectConstructor | { type: ObjectConstructor }]
|
||||||
? Record<string, any>
|
? Record<string, any>
|
||||||
: T extends BooleanConstructor | { type: BooleanConstructor }
|
: [T] extends [BooleanConstructor | { type: BooleanConstructor }]
|
||||||
? boolean
|
? boolean
|
||||||
: T extends DateConstructor | { type: DateConstructor }
|
: [T] extends [DateConstructor | { type: DateConstructor }]
|
||||||
? Date
|
? Date
|
||||||
: T extends Prop<infer V, infer D> ? (unknown extends V ? D : V) : T
|
: [T] extends [Prop<infer V, infer D>]
|
||||||
|
? (unknown extends V ? D : V)
|
||||||
|
: T
|
||||||
|
|
||||||
export type ExtractPropTypes<O> = O extends object
|
export type ExtractPropTypes<O> = O extends object
|
||||||
? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
|
? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
ComponentPublicInstance,
|
ComponentPublicInstance,
|
||||||
ComponentOptions,
|
ComponentOptions,
|
||||||
SetupContext,
|
SetupContext,
|
||||||
|
IsUnion,
|
||||||
h
|
h
|
||||||
} from './index'
|
} from './index'
|
||||||
|
|
||||||
@ -33,6 +34,9 @@ describe('with object props', () => {
|
|||||||
hhh: boolean
|
hhh: boolean
|
||||||
ggg: 'foo' | 'bar'
|
ggg: 'foo' | 'bar'
|
||||||
ffff: (a: number, b: string) => { a: boolean }
|
ffff: (a: number, b: string) => { a: boolean }
|
||||||
|
iii?: (() => string) | (() => number)
|
||||||
|
jjj: ((arg1: string) => string) | ((arg1: string, arg2: string) => string)
|
||||||
|
kkk?: any
|
||||||
validated?: string
|
validated?: string
|
||||||
date?: Date
|
date?: Date
|
||||||
}
|
}
|
||||||
@ -100,6 +104,16 @@ describe('with object props', () => {
|
|||||||
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
type: Function as PropType<(a: number, b: string) => { a: boolean }>,
|
||||||
default: (a: number, b: string) => ({ a: a > +b })
|
default: (a: number, b: string) => ({ a: a > +b })
|
||||||
},
|
},
|
||||||
|
// union + function with different return types
|
||||||
|
iii: Function as PropType<(() => string) | (() => number)>,
|
||||||
|
// union + function with different args & same return type
|
||||||
|
jjj: {
|
||||||
|
type: Function as PropType<
|
||||||
|
((arg1: string) => string) | ((arg1: string, arg2: string) => string)
|
||||||
|
>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
kkk: null,
|
||||||
validated: {
|
validated: {
|
||||||
type: String,
|
type: String,
|
||||||
// validator requires explicit annotation
|
// validator requires explicit annotation
|
||||||
@ -126,6 +140,13 @@ describe('with object props', () => {
|
|||||||
expectType<ExpectedProps['hhh']>(props.hhh)
|
expectType<ExpectedProps['hhh']>(props.hhh)
|
||||||
expectType<ExpectedProps['ggg']>(props.ggg)
|
expectType<ExpectedProps['ggg']>(props.ggg)
|
||||||
expectType<ExpectedProps['ffff']>(props.ffff)
|
expectType<ExpectedProps['ffff']>(props.ffff)
|
||||||
|
if (typeof props.iii !== 'function') {
|
||||||
|
expectType<undefined>(props.iii)
|
||||||
|
}
|
||||||
|
expectType<ExpectedProps['iii']>(props.iii)
|
||||||
|
expectType<IsUnion<typeof props.jjj>>(true)
|
||||||
|
expectType<ExpectedProps['jjj']>(props.jjj)
|
||||||
|
expectType<ExpectedProps['kkk']>(props.kkk)
|
||||||
expectType<ExpectedProps['validated']>(props.validated)
|
expectType<ExpectedProps['validated']>(props.validated)
|
||||||
expectType<ExpectedProps['date']>(props.date)
|
expectType<ExpectedProps['date']>(props.date)
|
||||||
|
|
||||||
@ -160,6 +181,13 @@ describe('with object props', () => {
|
|||||||
expectType<ExpectedProps['fff']>(props.fff)
|
expectType<ExpectedProps['fff']>(props.fff)
|
||||||
expectType<ExpectedProps['hhh']>(props.hhh)
|
expectType<ExpectedProps['hhh']>(props.hhh)
|
||||||
expectType<ExpectedProps['ggg']>(props.ggg)
|
expectType<ExpectedProps['ggg']>(props.ggg)
|
||||||
|
if (typeof props.iii !== 'function') {
|
||||||
|
expectType<undefined>(props.iii)
|
||||||
|
}
|
||||||
|
expectType<ExpectedProps['iii']>(props.iii)
|
||||||
|
expectType<IsUnion<typeof props.jjj>>(true)
|
||||||
|
expectType<ExpectedProps['jjj']>(props.jjj)
|
||||||
|
expectType<ExpectedProps['kkk']>(props.kkk)
|
||||||
|
|
||||||
// @ts-expect-error props should be readonly
|
// @ts-expect-error props should be readonly
|
||||||
expectError((props.a = 1))
|
expectError((props.a = 1))
|
||||||
@ -180,6 +208,14 @@ describe('with object props', () => {
|
|||||||
expectType<ExpectedProps['fff']>(this.fff)
|
expectType<ExpectedProps['fff']>(this.fff)
|
||||||
expectType<ExpectedProps['hhh']>(this.hhh)
|
expectType<ExpectedProps['hhh']>(this.hhh)
|
||||||
expectType<ExpectedProps['ggg']>(this.ggg)
|
expectType<ExpectedProps['ggg']>(this.ggg)
|
||||||
|
if (typeof this.iii !== 'function') {
|
||||||
|
expectType<undefined>(this.iii)
|
||||||
|
}
|
||||||
|
expectType<ExpectedProps['iii']>(this.iii)
|
||||||
|
const { jjj } = this
|
||||||
|
expectType<IsUnion<typeof jjj>>(true)
|
||||||
|
expectType<ExpectedProps['jjj']>(this.jjj)
|
||||||
|
expectType<ExpectedProps['kkk']>(this.kkk)
|
||||||
|
|
||||||
// @ts-expect-error props on `this` should be readonly
|
// @ts-expect-error props on `this` should be readonly
|
||||||
expectError((this.a = 1))
|
expectError((this.a = 1))
|
||||||
@ -214,6 +250,7 @@ describe('with object props', () => {
|
|||||||
fff={(a, b) => ({ a: a > +b })}
|
fff={(a, b) => ({ a: a > +b })}
|
||||||
hhh={false}
|
hhh={false}
|
||||||
ggg="foo"
|
ggg="foo"
|
||||||
|
jjj={() => ''}
|
||||||
// should allow class/style as attrs
|
// should allow class/style as attrs
|
||||||
class="bar"
|
class="bar"
|
||||||
style={{ color: 'red' }}
|
style={{ color: 'red' }}
|
||||||
@ -232,6 +269,7 @@ describe('with object props', () => {
|
|||||||
eee={() => ({ a: 'eee' })}
|
eee={() => ({ a: 'eee' })}
|
||||||
fff={(a, b) => ({ a: a > +b })}
|
fff={(a, b) => ({ a: a > +b })}
|
||||||
hhh={false}
|
hhh={false}
|
||||||
|
jjj={() => ''}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
6
test-dts/index.d.ts
vendored
6
test-dts/index.d.ts
vendored
@ -11,3 +11,9 @@ export function describe(_name: string, _fn: () => void): void
|
|||||||
export function expectType<T>(value: T): void
|
export function expectType<T>(value: T): void
|
||||||
export function expectError<T>(value: T): void
|
export function expectError<T>(value: T): void
|
||||||
export function expectAssignable<T, T2 extends T = T>(value: T2): void
|
export function expectAssignable<T, T2 extends T = T>(value: T2): void
|
||||||
|
|
||||||
|
export type IsUnion<T, U extends T = T> = (T extends any
|
||||||
|
? (U extends T ? false : true)
|
||||||
|
: never) extends false
|
||||||
|
? false
|
||||||
|
: true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user