TypeScript 中“R['length'] extends N”语法的解释

Explanation of " R['length'] extends N " syntax in TypeScript

TypeScript 新手,正在寻找一种方法来定义固定大小的数组并遇到 :

type Tuple<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never;
type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;

type Tuple9<T> = Tuple<T, 9>;
type Board9x9<P> = Tuple9<Tuple9<P>>;

...使用递归条件类型获得所需的结果。 我试图理解正在使用的语法,但我无法真正理解幕后发生的事情,尤其是在这一点上:R['length'] extends N.

我知道它会检查数组是否具有所需的长度,如果不是,它将使用额外的元素递归调用 _TupleOf,直到该条件变为真。但为什么会这样? 我搜索了答案,但找不到任何有用的东西。

如果应用于类型,R['length'] return 是作为数字的实际长度吗?为什么 extends 在这种情况下看起来像 == 运算符?

我也试过仔细检查它的行为是否如我在 playground 中所理解的那样(您可以将鼠标悬停在 bc 上以检查类型)并且似乎确实如此,还是不​​明白为什么。

任何link或解释?提前致谢!

因为:

  1. 元组的length属性类型是文字数字类型,等于元组中元素的数量。所以不仅仅是 number,而是 特定的 数字(例如 42)。
  2. 数字文字类型扩展 number(嗯...我不确定我为什么提到这个,但它在下面的例子中所以我会保留它。)
  3. 数字字面量类型仅“扩展”自身(与其相同或子类型)。
type TwoThings = [string, string];
type TwoThingsLength = TwoThings["length"];
//   ^? −−− type TwoThingsLength = 2

type IsNumber<T> = T extends number ? true : false;
type A = IsNumber<27>;
//   ^? −−− type A = true
type B = IsNumber<"example">;
//   ^? −−− type B = false

type IsThisNumber<T, Num> = T extends Num ? true : false;
type C = IsThisNumber<27, 27>;
//   ^? −−− type C = true
type D = IsThisNumber<27, 42>;
//   ^? −−− type D = false

// Which leads us to
type E = IsThisNumber<TwoThingsLength, 2>; // true, they're the same literal number
//   ^? −−− type E = true
type F = IsThisNumber<TwoThingsLength, 3>; // false, they aren't
//   ^? −−− type F = false

Playground link

所以 R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]> 的工作人员是:

  • 如果 R['length'] 与目标长度 N 相同,则评估为 R 类型本身
  • 如果不是,则创建一个新的元组类型,其中包含元素 T 加上所有先前的元素 (...R)——例如,添加一个——并递归