共计 2176 个字符,预计需要花费 6 分钟才能阅读完成。
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
-> string
、Number
-> number
、Boolean
-> 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 预览链接
效果图
正文完
发表至: javascript
2019-06-12