Yuzhe's Blog

yuzhes

TC949: AnyOf

AnyOf

Challenge Link

Problem

Implement Python’s any function in the type system. The type takes an Array and returns true if any element of the Array is truthy. If the Array is empty, return false.

type Sample1 = AnyOf<[1, "", false, [], {}]> // expected to be true
type Sample2 = AnyOf<[0, "", false, [], {}]> // expected to be false

Solution

type Falsy = 0 | "" | false | [] | { [key: string]: never } | null | undefined

type AnyOf<T extends readonly any[]> = T[number] extends Falsy ? false : true

Deep Dive

Understanding Falsy Values in TypeScript

In JavaScript, the following values are considered falsy:

The challenge extends JavaScript’s falsy definition to include empty arrays and empty objects.

Solution Breakdown

  1. Define Falsy type: We create a union of all falsy types

    • { [key: string]: never } represents an empty object — an object with no properties
  2. Use T[number]: This creates a union of all element types in the tuple

  3. Conditional check: T[number] extends Falsy checks if ALL elements are falsy

    • If every element extends Falsy, return false
    • Otherwise, return true

Alternative Approach: Recursive Solution

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

This recursively checks each element. If we find a truthy element, return true immediately.

Edge Case: Empty Object Detection

The tricky part is detecting empty objects. { [key: string]: never } works because:

Key Takeaways

  1. Indexed access T[number] distributes tuple types into a union
  2. extends with unions checks if ALL members of the left side extend the right side
  3. Empty object detection uses { [key: string]: never } pattern
  4. The challenge redefines falsy to include [] and {}, unlike JavaScript