LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

TypeScriptの型パターンマッチング

Posted at
1 / 10

今日のお題

TypeScript 2.8に入る機能のお話

型のパターンマッチングができるようになる


1. Conditional Types

読んで字の如く、型定義における条件分岐

type MyCondition<T, U, X, Y> = T extends U ? X : Y;

「TがUに代入可能であればXを、そうでなければY」という型


誕生した背景


差分の表現方法

Conditional Typesは、Union Typesについて、分配律が成立

(T1 | T2) extends U ? X : Y = (T1 extends U ? X : Y) | (T2 extends U ? X : Y)

この性質とneverを組み合わせると、差分や絞込が簡単に表現できる

type Diff<T, U> = T extends U ? never : T;

type Result = Diff<("hoge" | "foo" | "piyo"), "foo">
// "hoge" | never | "piyo" = "hoge" | "piyo"

和型、ボトム型、条件型で差分型が表現できた、ということ


ちなみに keyof, Mapped typesと組み合わせると...

type Diff<T, U> = T extends U ? never : T;
type $Diff<T, U> = { [P in Diff<keyof T, keyof U>]: T[P] };
type Props = { name: string, age: number };
type DefaultProps = { age: number };
type RequiredProps = $Diff<Props, DefaultProps>;

declare function setProps<T extends RequiredProps>(props: T): void;

setProps({ name: "foo" });
setProps({ name: "foo", age: 42 }); // you can pass extra props too
setProps({ age: 42 }); // error, name is required

再帰型の終端指定

Mapped Typesによる再帰型で「終端」が表現可能に

type primitive = string | number | boolean | undefined | null;
type DeepReadonly<T> = T extends primitive ? T : DeepReadonlyObject<T>;
type DeepReadonlyObject<T> = {
    readonly [P in keyof T]: DeepReadonly<T[P]>;
};


これだけでも割とすごい


2. Type Inference in Conditional Types

infer でマッチした型をキャプチャできる

type ReturnType<T> = T extends ((...args: any[]) => infer R) ? R : never;
type ResolvedType<T> =
  T extends Promise<infer R> ? R :
  T extends Observable<infer R> ? R :
  T;

所感

  • おそらく、日常使いするものではなさそう
  • 既存ライブラリの型定義を書くときに捗りそう

それでは楽しい型ライフを :angel:

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up