Includes
挑战
在类型系统中实现 JavaScript 的Array.includes
函数,接收 2 个参数。它的输出应该
是布尔类型true
或false
。例如:
// expected to be `false`
type isPillarMen = Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Dio">;
解答
我们首先编写接受两个参数的类型:T
(元组)和U
(我们正在寻找的)。
type Includes<T, U> = never;
在我们真正能在元组中找到一些东西之前,将其“转换”为联合(union)比会元组(tuple)
更容易一些。为此,我们可以使用索引类型(indexed types)。如果我们访
问T[number]
,TypeScript 会返回T
中所有元素的联合(union)。例如,如果你有一
个T = [1, 2, 3]
,通过T = [number]
访问将返回1 | 2 | 3
。
type Includes<T, U> = T[number];
但是,这里有一个错误,“Type ‘number’ cannot be used to index type ‘T’”。这是因为
类型T
没有约束。我们需要告诉 TypeScript,T
是一个数组。
type Includes<T extends unknown[], U> = T[number];
我们有了元素的联合(union)。我们如何检查元素是否存在于联合(union)中?条件类型 分配(Distributive)!我们可以为联合(union)编写条件类型,TypeScript 会自动将条 件应用到联合(union)的每个元素上。
例如,如果你写2 extends 1 | 2
,TypeScript 实际上会把它替换成 2 个条件语
句2 extends 1
和2 extends 2
。
我们可以利用它检查U
是否在T[number]
中,如果在则返回 true。
type Includes<T extends unknown[], U> = U extends T[number] ? true : false;
评论