即使使用最新的typescript@3.4.5和严格模式,通过联合类型的键分配字典值时,TypeScript看起来也不健全。
这是一个已知问题吗?有人可以指出我相关的错误报告吗?
tsconfig.json
{
"compilerOptions": {
"strict": true
}
}
test.ts
interface A {
a: number;
b: string;
}
interface B {
a: string;
b: number;
}
function someFunction(a: A, b: B, field: 'a'|'b'): void {
// ...
// A lot of unrelated code
// ...
b[field] = a[field];
// ...
// A lot of unrelated code
// ...
}
const a = { a: 1, b: '1' };
const b = { a: '2', b: 2 };
someFunction(a, b, 'a');
// type of B.a is string, but in this instance a number is assigned
// and TypeScript fails to warn about it even in strict mode :-(
console.log(typeof b['a']);
使用typescript@3.4.5和ts-node(ts-node test.ts
)运行此代码会产生
number
答案 0 :(得分:3)
是的,这是不完善的,它是类型系统中的一个已知漏洞,将通过此PR在3.5中修复。从PR:
借助此PR,我们可以通过多种方式提高索引访问类型的可靠性:
- 在类型关系的源侧发生索引访问
T[K]
时,它解析为T[K]
选择的属性的并集类型,但是在目标侧发生类型关系,现在解析为T[K]
选择的属性的交集类型。以前,目标端也将解析为联合类型,这是不合理的。- 给定具有约束
T
的类型变量C
,当在类型关系的目标端发生索引访问T[K]
时,C
中的索引签名现在变为忽略了。这是因为实际上T
的类型参数并不需要具有索引签名,而只需要具有匹配类型的属性即可。- 类型
{ [key: string]: number }
与映射类型{ [P in K]: number }
不再相关,其中K
是类型变量。这与源中的字符串索引签名与目标中的实际属性不匹配相符。- 索引访问类型的约束现在可以更全面地研究。例如,在给定类型变量
T
和K extends 'a' | 'b'
的情况下,现在认为类型{ a: T, b: T }[K]
和T
是相关的。
注意:突出显示了可能与此问题相关的位。
您现在可以在npm install typescript@next
上进行安装,以在3.5上试用一下,您将得到预期的错误。