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

理解特定TypeScript索引签名的含义,typescript,Typescript,我在看Anders Hejlsberg在github线程中提供的Diff方法: 我不太理解这个索引签名{[x:string]:never}在类型上下文中的含义 type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T]; type Diff=({[P in T]:P}&{[P in U]:never

我在看Anders Hejlsberg在github线程中提供的
Diff
方法:

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

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

它依赖于这样一个事实,即具有字符串索引签名的对象可以使用任何字符串进行索引

但它还是不适合我


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

注意:今天不要在打字脚本中使用
Diff
。自从typescript 2.8以来,我们在默认类型中内置了一个更好的diff替代品,名为
Exclude
Exclude
使用条件类型来更清晰地筛选类型

Diff
过去是过滤字符串文本类型的技巧。该技巧使用了
never

  • T&never
    never
  • T | never
    is
    T
第一个映射类型
{[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:,b:never})[“a”|“b”]
将是
“a”| never
所以
“a”

但这就是我们的问题所在。回到typescript 2.4中,如果我们按照
T
进行索引,我们会得到一个错误(这个
type Diff=({[P in T]:P}&{[P in U]:never})[T];
这是一个错误),因为typescript不满意先前定义的交集可以通过
T
进行索引。在当前的typescript()中,这实际上不再是一个问题。但是在这个技巧有用的时候,我们需要一些额外的东西来说服编译器允许通过
T
进行索引


这个额外的东西是
{[x:string]:never}
。它允许通过任何字符串进行索引(因此
[T]
可以工作)。而且它不会影响索引操作的结果,因为任何其他键值都将与索引中的此
never
联合,并且联合中的
never
会融化。

哪一部分
[x:string]
从不
?这是过滤字符串文本类型的一个非常古老的技巧。现在条件类型,特别是预定义的
Exclude
条件类型做了同样的事情,但还是要感谢你为我搔痒——尽管这不再是一个问题了,我还是要知道:)@Jordan解释复杂类型总是很有趣,也许我们应该开始一个类型历史页面,对于旧类型的黑客,我刚刚开始深入研究TS,所以这是我所知道的第一个类型的黑客(实际上我可能有一个与解构相关的),但我可以在TS github repo中为此建议一个新的wiki页面。您知道这是否特定于任何
类型
交叉点,涉及值为
从不
的属性?