TC949: AnyOf
大约 2 分钟
AnyOf
题目
在类型系统中实现 Python 的 any 函数。该类型接收一个数组,如果数组中任一元素为真值则返回 true。如果数组为空,返回 false。
type Sample1 = AnyOf<[1, "", false, [], {}]> // 应为 true
type Sample2 = AnyOf<[0, "", false, [], {}]> // 应为 false解答
type Falsy = 0 | "" | false | [] | { [key: string]: never } | null | undefined
type AnyOf<T extends readonly any[]> = T[number] extends Falsy ? false : true深入解析
TypeScript 中的假值
JavaScript 中以下值被视为假值:
0""(空字符串)false[](空数组 — 注意:JS 中这是真值,但本题视为假值){}(空对象 — 同上)nullundefined
本题扩展了 JavaScript 的假值定义,包含了空数组和空对象。
解法拆解
定义 Falsy 类型:创建所有假值类型的联合
{ [key: string]: never }表示空对象 — 没有任何属性的对象
使用
T[number]:将元组中所有元素类型转为联合类型条件判断:
T[number] extends Falsy检查是否所有元素都是假值- 如果每个元素都 extends
Falsy,返回false - 否则返回
true
- 如果每个元素都 extends
另一种解法:递归方案
type Falsy = 0 | "" | false | [] | { [key: string]: never } | null | undefined
type AnyOf<T extends readonly any[]> = T extends [infer First, ...infer Rest]
? First extends Falsy
? AnyOf<Rest>
: true
: false递归检查每个元素。一旦找到真值元素,立即返回 true。
边界情况:空对象检测
检测空对象是本题的难点。{ [key: string]: never } 有效是因为:
- 它描述了一个对象,其中每个字符串键都映射到
never - 因为
never没有值,所以不可能存在任何键 - 因此,只有
{}满足此约束
核心要点
- 索引访问
T[number]将元组类型分发为联合类型 - 联合类型的
extends检查左侧的所有成员是否都 extends 右侧 - 空对象检测 使用
{ [key: string]: never }模式 - 本题重新定义了假值,包含
[]和{},与 JavaScript 不同
