在严格模式下通过联合类型的键对字典进行不安全的字典值分配

时间:2019-05-08 14:11:22

标签: typescript

即使使用最新的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

1 个答案:

答案 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是类型变量。这与源中的字符串索引签名与目标中的实际属性不匹配相符。
  •   
  • 索引访问类型的约束现在可以更全面地研究。例如,在给定类型变量TK extends 'a' | 'b'的情况下,现在认为类型{ a: T, b: T }[K]T是相关的。
  •   

注意:突出显示了可能与此问题相关的位。 您现在可以在npm install typescript@next上进行安装,以在3.5上试用一下,您将得到预期的错误。