Yuzhe's Blog

yuzhes

TC949: AnyOf

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 中以下值被视为假值:

本题扩展了 JavaScript 的假值定义,包含了空数组和空对象。

解法拆解

  1. 定义 Falsy 类型:创建所有假值类型的联合

    • { [key: string]: never } 表示空对象 — 没有任何属性的对象
  2. 使用 T[number]:将元组中所有元素类型转为联合类型

  3. 条件判断T[number] extends Falsy 检查是否所有元素都是假值

    • 如果每个元素都 extends Falsy,返回 false
    • 否则返回 true

另一种解法:递归方案

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 } 有效是因为:

核心要点

  1. 索引访问 T[number] 将元组类型分发为联合类型
  2. 联合类型的 extends 检查左侧的所有成员是否都 extends 右侧
  3. 空对象检测 使用 { [key: string]: never } 模式
  4. 本题重新定义了假值,包含 []{},与 JavaScript 不同