Improved Intersection Reduction, Union Compatibility, and Narrowing

TL;DR

undefined,nullを除外する推論が改善された。

undefined,nullを除外するNarrowing

以前のバージョンでは、{}にundefinedとnullが入る余地があった。 これによりunknown型やジェネリクスなどのNarrowingで期待どおりの結果が得られない事があった。

unknownを使ったNarrowing

function fn(x: unknown) {
    if (x === undefined || x === null) {
        throw new Error("");
    }
    return x;
}

declare const x: unknown;
fn(x);

以前のバージョンでは推論結果がunknownとなってしまう。

fn(x); // unknown

4.8ではundefindとnullは含まれなくなった。

fn(x); // {}

ジェネリクスを使ったNarrowing

function fn<T>(x: T) {
    if (x === undefined || x === null) {
        throw new Error("");
    }
    return x;
}

declare const x: null | undefined | number;
fn(x);

以前のバージョンでは推論結果にundefinedまたはnullが含まれてしまう。

fn(x); // null | undefined | number

4.8ではundefinedとnullは含まれなくなった。

fn(x): // number

ifを使ったNarrowing

declare const x: unknown;

if (x) {
    x;
}

以前のバージョンではunknownのまま。

if (x) {
    x; // unknown
}

4.8ではundefinedとnullが除外され、{}と推論される。

if (x) {
    x; // {}
}

NonNullable

NonNullableの定義も刷新された。

- type NonNullable<T> = T extends null | undefined ? never : T;
+ type NonNullable<T> = T & {};

4.8ではunknownからundefinedとnullを除外した型を表現できるようになった。

type A = NonNullable<unknown>; // {}

以下のコードは、以前のバージョンでは期待通りの結果が得られなかった。

function fn<T>(x: T): NonNullable<T> {
  if (x !== null && x !== undefined) {
      return x; // ❌ ERROR: NonNullable<T>と互換性がない
  }
  throw new Error("");
}

declare const x: unknown;
const y = fn(x); // ❌ unknownと推論される

4.8では期待どおりの結果が得られるようになった。

function fn<T>(x: T): NonNullable<T> {
  if (x !== null && x !== undefined) {
      return x;
  }
  throw new Error("");
}

declare const x: unknown;
const y = fn(x); // ✅ {}と推論される

Last updated