了解特定TypeScript索引签名的含义

时间:2019-06-09 19:01:48

标签: typescript

我正在看Anders Hejlsberg在这个github线程中提供的Diff方法:https://github.com/microsoft/TypeScript/issues/12215#issuecomment-307871458

在类型的上下文中,我不太了解此索引签名{ [x: string]: never }的含义

type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T]; 

他解释

  

它依赖于以下事实:带有字符串索引签名的对象可以用任何字符串索引。

但它仍然没有为我点击

这里的任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:4)

注意:今天不要在打字稿中使用Diff。从2.8版打字稿开始,我们有了更好的替代方法,将diff内置到称为Exclude的默认类型中。 Exclude使用条件类型来过滤类型更简洁。

Diff曾经是过滤字符串文字类型的技巧。这个技巧使用never

的两个特殊属性
  • T & nevernever
  • T | neverT

第一个映射类型{[P in T]: P }产生一个类型,该类型的每个键的值都与键名相同。因此,如果T'a' | 'b',则此映射类型将产生{a : "a", b: "b"}

第二个映射类型会为我们要删除的那些键生成一个never的类型。因此,如果U'b',则此映射类型将产生{ b: never }

将这两个相交会产生{a : "a", b: "b"} & { b: never },而{a : "a", b: "b" & never }会减少为{a : "a", b: never }

如果我们要获得上述类型(即(... & ...)[T])的值的并集,则将得到Diff的结果,因为({a : "a", b: never })["a" | "b"]将是"a" | never所以"a"

但这是我们遇到的问题。回到打字稿2.4,如果我们用T进行索引,则会得到一个错误(这个type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never })[T];这是一个错误see playground),因为打字稿不满足于先前定义的交集是可被T索引。在当前的打字稿(see)中,这实际上不再是问题。但是当这个技巧有用时,我们需要一些额外的东西来说服编译器允许通过T进行索引。

这是{ [x: string]: never }。它将允许按任何字符串进行索引(因此[T]将起作用)。而且它不会影响索引操作的结果,因为其他任何键值都将与索引中的never并入联合,而联合中的never会消失。