import type { ExtractPropTypes, PropType } from 'vue' import type { tnPropKey } from './runtime' import type { IfNever, UnknowToNever, WriteableArray } from './util' type Value = T[keyof T] /** * 提取单个 prop 的参数类型 * * @example * ExtractPropType<{ type: StringConstructor }> => string | undefined * ExtractPropType<{ type: StringConstructor, required: true }> => string * ExtractPropType<{ type: BooleanConstructor }> => boolean */ export type ExtractPropType = Value< ExtractPropTypes<{ key: T }> > /** * 通过 `ExtractPropTypes` 提取类型,接受 `PropType`、`XXXConstructor`、`never`... * * @example * ResolvePropType => boolean * ResolvePropType> => T */ export type ResolvePropType = IfNever< T, never, ExtractPropType<{ type: WriteableArray required: true }> > /** * 合并 Type、Value、Validator 的类型 * * @example * EpPropMergeType => 1 | "1" // ignores StringConstructor * EpPropMergeType => string | number */ export type TnPropMergeType = | IfNever, ResolvePropType, never> | UnknowToNever | UnknowToNever /** * 处理输入参数的默认值(约束) */ export type TnPropInputDefault< Required extends boolean, Default > = Required extends true ? never : Default extends Record | Array ? () => Default : (() => Default) | Default /** * 原生 prop `类型,BooleanConstructor`、`StringConstructor`、`null`、`undefined` 等 */ export type NativePropType = | ((...args: any) => any) | { new (...args: any): any } | undefined | null export type IfNativePropType = [T] extends [NativePropType] ? Y : N /** * prop 输入参数(约束) * * @example * EpPropInput * { type?: StringConstructor | undefined; required?: true | undefined; values?: readonly "a"[] | undefined; validator?: ((val: any) => boolean) | ((val: any) => val is never) | undefined; default?: undefined; } */ export type TnPropInput< Type, Value, Validator, Default extends TnPropMergeType, Required extends boolean > = { type?: Type required?: Required values?: readonly Value[] validator?: ((val: any) => val is Validator) | ((val: any) => boolean) default?: TnPropInputDefault } /** * prop 输出参数(约束) * * @example * EpProp<'a', 'b', true> * { readonly type: PropType<"a">; readonly required: true; readonly validator: ((val: unknown) => boolean) | undefined; readonly default: "b"; __epPropKey: true; } */ export type TnProp = { readonly type: PropType readonly required: [Required] extends [true] ? true : false readonly validator: ((val: unknown) => boolean) | undefined [tnPropKey]: true } & IfNever export type IfTnProp = T extends { [tnPropKey]: true } ? Y : N export type TnPropConvert = Input extends TnPropInput< infer Type, infer Value, infer Validator, any, infer Required > ? TnPropFinalized : never export type TnPropFinalized = TnProp< TnPropMergeType, UnknowToNever, Required > export {}