rfc 中类型推导部分 Type Inference

预期想实现的效果

createComponent({  props: {    foo: {      type: String,      required: true    },    bar: {      type: Number    },    boo: Boolean,    options: (null as any) as { msg: string },    requiredOptions: {      type: (null as any) as { msg: string },      required: true    }  } as const,  setup(props) {    props.foo; // string    props.bar; // number | undefined    props.boo; // boolean | undefined    props.options; // {msg: string } | undefined    props.requiredOptions; // {msg: string }  }});

String -> stringNumber -> numberBoolean -> boolean

在 ts 中

  • String对应的类型是StringConstructor
  • Number对应的类型是NumberConstructor
  • Boolean对应的类型是BooleanConstructor

但是,我们想要实现的是转换成小写的string | number | boolean

所以我们写个泛型来转换

type NormalizeType<T> = T extends StringConstructor  ? string  : T extends NumberConstructor  ? number  : T extends BooleanConstructor  ? boolean  : T;

playground 预览链接

定义 prop 的类型

type BuiltInType<T> =  | StringConstructor  | NumberConstructor  | BooleanConstructor  | T;

留个泛型是给复杂类型做兼容
rfc 复杂的 prop 类型

定义createComponent函数接收的props类型

type DefaultType<T> = {  [key: string]:    | {        type?: BuiltInType<T>;        require?: boolean;      }    | BuiltInType<T>;};

最关键的一步根据输入的props类型计算出来setup函数接收的形参props类型

type ReflexType<T> = {  [key in keyof T]: T[key] extends { type: infer TYPE; required: true }    ? NormalizeType<TYPE>    : T[key] extends { type: infer TYPE }    ? NormalizeType<TYPE> | undefined    : NormalizeType<T[key]> | undefined};

组合出来createComponent函数定义

function createComponent<T extends DefaultType<any>>(props: {  props: T;  setup(props: ReflexType<T>): any;}) {}

完整代码

type BuiltInType<T> =  | StringConstructor  | NumberConstructor  | BooleanConstructor  | T;type NormalizeType<T> = T extends StringConstructor  ? string  : T extends NumberConstructor  ? number  : T extends BooleanConstructor  ? boolean  : T;type ReflexType<T> = {  [key in keyof T]: T[key] extends { type: infer TYPE; required: true }    ? NormalizeType<TYPE>    : T[key] extends { type: infer TYPE }    ? NormalizeType<TYPE> | undefined    : NormalizeType<T[key]> | undefined};type DefaultType<T> = {  [key: string]: { type?: BuiltInType<T>; require?: boolean } | BuiltInType<T>;};function createComponent<T extends DefaultType<any>>(props: {  props: T;  setup(props: ReflexType<T>): any;}) {}createComponent({  props: {    foo: {      type: String,      required: true    },    bar: {      type: Number    },    boo: Boolean,    options: (null as any) as { msg: string },    requiredOptions: {      type: (null as any) as { msg: string },      required: true    }  } as const,  setup(props) {    props.foo;    props.bar;    props.boo;    props.options;    props.requiredOptions;  }});

playground 预览链接

效果图