我正在编写一个转换器,该转换器使用查找对象将元组数组转换为对象,该对象告诉函数哪个字符串映射到哪些属性。但是,我找不到一种方法告诉打字稿它是具有特定类型的元组的数组,生成的元组始终是联合。看起来是这样的:
interface EndObj {
a: number;
b: string;
c?: number;
}
interface InitObj {
d: string;
e: string;
f: string;
}
const map = {
d: 'a',
e: 'b',
f: 'c'
} as const;
type MapType = typeof map;
type ResultTuple<T extends keyof InitObj> = [T, EndObj[MapType[T]]];
type ResultTupleArray = ResultTuple<keyof InitObj>[];
const resultObj: ResultTupleArray = [['d', 1], ['e', 3], ['f', 3]]; // invalid! the value of 'e' should only allow strings
我认为类型脚本允许这样做的原因是,因为ResultTupleArray
是用定义的keyof InitObj
,因此生成的元组数组泛型始终是相同的,因此T
将始终是相同的,而不是每个数组条目都特定,因此只能用并集来描述。
这是我发现的方式:
const undetected: ResultTuple<keyof InitObj> = ['e', 4]; // should be invalid
const detected: ResultTuple<'e'> = ['e', 4]; // actually shows an error for 4 (Type 'number' is not assignable to type 'string'.)
对于上下文,这里是转换器的外观:
function mapInitToEnd(resultO: ResultTupleArray) {
const endObj: EndObj = {
a: -1,
b: ''
};
for (const tuple of resultO) {
const [key, val] = tuple;
const mappedKey = map[key];
endObj[mappedKey] = val;
}
return endObj;
}
有没有办法告诉打字稿,泛型仅对元组数组中的每个条目有效,而对整个数组无效?
您希望分布ResultTuple
定义,以便如果T
是键的并集,则结果是元组的并集。在给定代码的情况下,完成此操作的最简单方法是使定义成为分布式条件类型,该条件类型免费提供以下行为:
type ResultTuple<T extends keyof InitObj> = T extends any ? [T, EndObj[MapType[T]]] : never;
当类型参数为T extends U ? X : Y
where时,将启动分布式条件类型T
。因此,要使此事情发生在上面,我们添加了否则没有用的T extends any ? ... : never
检查。现在,您的代码将给您您期望的错误:
const resultObj: ResultTupleArray = [['d', 1], ['e', 3], ['f', 3]]; // error!
// number not assignable to string ----------> ~~~~~~~~
还有其他方法可以实现此行为。例如,通过构建映射类型并立即查找其属性:
type ResultTuple<T extends keyof InitObj> = { [K in T]: [K, EndObj[MapType[K]]] }[T];
两种方法都应该起作用。
好吧,希望能有所帮助;祝好运!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句