← All tasksTypeScript · Middle

Type guards: isDefined, isString, isOneOf

Write three checks after which TypeScript narrows the value's type.

isDefined(value): not null and not undefined; [1, null, 2].filter(isDefined) should give number[], and 0 and "" are values too. isString(value): a string. isOneOf(values) returns a check for one of the listed values: after isOneOf(["red", "green"] as const)(c) the type of c is "red" | "green".

Tests (6)

Type tests are checked by the TypeScript compiler in strict mode. Expect<Equal<A, B>> passes when the types match exactly, and // @ts-expect-error passes when the next line does not compile. The first run downloads the compiler, so it takes a few seconds.

  1. types
    const xs = [1, null, 2, undefined].filter(isDefined);
    type _ = Expect<Equal<typeof xs, number[]>>;
  2. types
    const v: unknown = 'x';
    if (isString(v)) {
      type _ = Expect<Equal<typeof v, string>>;
    }
  3. types
    const isColor = isOneOf(['red', 'green'] as const);
    const c: unknown = 'red';
    if (isColor(c)) {
      type _ = Expect<Equal<typeof c, 'red' | 'green'>>;
    }
  4. expect([1, null, 2, undefined, 0, ''].filter(isDefined)).toEqual([1, 2, 0, '']);
  5. expect(isString('a')).toBe(true);
    expect(isString(1)).toBe(false);
    expect(isString(null)).toBe(false);
  6. const isColor = isOneOf(['red', 'green']);
    expect(isColor('red')).toBe(true);
    expect(isColor('blue')).toBe(false);