import { Data } 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
// prettier-ignore
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 FunctionConstructor
? Function
: T extends Prop
? unknown extends V
? D extends null | undefined
? V
: D
: ExtractCorrectPropType
: 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 }
: {}