/
componentProps.ts
76 lines (61 loc) · 2.49 KB
/
componentProps.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { Data } from './common'
export type ComponentPropsOptions<P = Data> =
| ComponentObjectPropsOptions<P>
| string[]
export type ComponentObjectPropsOptions<P = Data> = {
[K in keyof P]: Prop<P[K]> | null
}
export type Prop<T, D = T> = PropOptions<T, D> | PropType<T>
type DefaultFactory<T> = () => T | null | undefined
export interface PropOptions<T = any, D = T> {
type?: PropType<T> | true | null
required?: boolean
default?: D | DefaultFactory<D> | null | undefined | object
validator?(value: unknown): boolean
}
export type PropType<T> = PropConstructor<T> | PropConstructor<T>[]
type PropConstructor<T> =
| { new (...args: any[]): T & object }
| { (): T }
| { new (...args: string[]): Function }
type RequiredKeys<T> = {
[K in keyof T]: T[K] extends { required: true } | { default: never } ? K : never
}[keyof T]
type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>
type ExtractFunctionPropType<
T extends Function,
TArgs extends Array<any> = any[],
TResult = any
> = T extends (...args: TArgs) => TResult ? T : never
type ExtractCorrectPropType<T> = T extends Function
? ExtractFunctionPropType<T>
: Exclude<T, Function>
// prettier-ignore
type InferPropType<T> = T extends null
? any // null & true would fail to infer
: 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`
: T extends ObjectConstructor | { type: ObjectConstructor }
? Record<string, any>
: T extends BooleanConstructor | { type: BooleanConstructor }
? boolean
: T extends DateConstructor | { type: DateConstructor}
? Date
: T extends FunctionConstructor
? Function
: T extends Prop<infer V, infer D>
? unknown extends V
? D
: ExtractCorrectPropType<V>
: T
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 }
type DefaultKeys<T> = {
[K in keyof T]: T[K] extends { default: any } ? K : never
}[keyof T]
// extract props which defined with default from prop options
export type ExtractDefaultPropTypes<O> = O extends object
? { [K in DefaultKeys<O>]: InferPropType<O[K]> }
: {}