我有一个Transformer界面:
interface Transformer<K> {
type: string,
apply<K>(data: K) : K
}
我想创建2个扩展Transformer
的界面
interface NumberTransformer extends Transformer<number> {
type: 'number',
apply<number>(data: number) : number
}
interface StringTransformer extends Transformer<string> {
type: 'string',
apply<string>(data: string) : string
}
这会引发2个TS错误(TS6133) 'string'/'number' is declared but its value is never read
,我不知道为什么
然后,在Transformer []列表中,我希望能够将type
参数用作类型防护,例如
const a : DataTransformer<??>[] = [{
type: 'number',
apply: (n :number) => n * 10
},
{
type: 'string',
apply: (str :string) => str.substr(0,1)
}];
a.forEach(s => {
if (s.type === 'string')
//s.apply is string => string type
});
但是我不知道a
的类型应该是什么? DataTransformer<any>
吗?
答案 0 :(得分:1)
type TransformerKeyType = {
'number': number,
'string': string,
}
interface DataTransformer<T extends keyof TransformerKeyType> {
type: T,
apply(data: TransformerKeyType[T]) : TransformerKeyType[T]
}
type NumberTransformer = DataTransformer<'number'>;
type StringTransformer = DataTransformer<'string'>;
const a : (DataTransformer<'number'> | DataTransformer<'string'>)[] = [{
type: 'number',
apply: (n) => n * 10
},
{
type: 'string',
apply: (str) => str.substr(0,1)
}];
a.forEach(s => {
if (s.type === 'string') {
s // here properly we have DataTransformer<'string'>
}
});
说明:
TransformerKeyType
是一种类型,它使我们在字符串和类型之间建立联系。这样我们就可以轻松地将字符串'number'
映射为类型number
DataTransformer
作为通用参数,它仅占用TransformerKeyType
的键,因此只占用number
或string
。并且该类型的正文自动通过说K
为K
来设置正确的TransformerKeyType[T]
。因此,请在T
中键入给定属性TransformerKeyType
。
type NumberTransformer = DataTransformer<'number'>;
是我们类型的实例。使用类型number
(DataTransformer<'number'> | DataTransformer<'string'>)[]
表示我们有一个数组,其中包含或带数字的DataTransformer或带字符串的DataTransformer。这样很好用,因为您无需在apply函数中声明参数类型,并且可以将n => n * 10
保留为数字的类型。