import { Data, IfAny } from './common'
export type ComponentPropsOptions
=
| ComponentObjectPropsOptions
| string[]
export type ComponentObjectPropsOptions
= {
[K in keyof P]: Prop
| null
}
export type Prop = PropOptions | PropType
type DefaultFactory = () => T | null | undefined
export interface PropOptions {
type?: PropType | true | null
required?: boolean
default?: D | DefaultFactory | null | undefined | object
validator?(value: unknown): boolean
}
export type PropType = PropConstructor | PropConstructor[]
type PropConstructor =
| { (): T }
| { new (...args: never[]): T & object }
| { new (...args: string[]): Function }
type RequiredKeys = {
[K in keyof T]: T[K] extends
| { required: true }
| { default: any }
| BooleanConstructor
| { type: BooleanConstructor }
? K
: never
}[keyof T]
type OptionalKeys = Exclude>
type ExtractFunctionPropType<
T extends Function,
TArgs extends Array = any[],
TResult = any
> = T extends (...args: TArgs) => TResult ? T : never
type ExtractCorrectPropType = T extends Function
? ExtractFunctionPropType
: Exclude
type InferPropType = [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
: [T] extends [BooleanConstructor | { type: BooleanConstructor }]
? boolean
: [T] extends [DateConstructor | { type: DateConstructor }]
? Date
: [T] extends [(infer U)[] | { type: (infer U)[] }]
? U extends DateConstructor
? Date | InferPropType
: InferPropType
: [T] extends [Prop]
? unknown extends V
? IfAny
: V
: T
export type ExtractPropTypes = {
// 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
[K in keyof Pick>]?: InferPropType
}
type DefaultKeys = {
[K in keyof T]: T[K] extends
| {
default: any
}
| BooleanConstructor
| { type: BooleanConstructor }
? T[K] extends {
type: BooleanConstructor
required: true
}
? never
: K
: never
}[keyof T]
// extract props which defined with default from prop options
export type ExtractDefaultPropTypes = O extends object
? // use `keyof Pick>` instead of `DefaultKeys` to support IDE features
{ [K in keyof Pick>]: InferPropType }
: {}