Dev Study
← コース一覧

TypeScript

JavaScript に型を加えた言語 TypeScript を、公式ハンドブックの流れに沿って基礎から学びます。型注釈の書き方から始めて、ユニオン型と絞り込み、ジェネリクス、ユーティリティ型、クラスまで、実務で毎日使う機能を1レッスン1テーマで身につけます。

公式ドキュメント: TypeScript Handbook

基本の型

  1. 1
    型注釈 — 変数に型を書く
    型注釈は、変数がどんな値を持つかをコードに明記する仕組みです。変数名の後ろにコロンと型名を書きます。たとえば let userName: string = "Taro" と書くと、userName には文字列しか入れられなくなります。
    実行可
  2. 2
    プリミティブ型 string / number / boolean
    TypeScript で最もよく使う基本の型が string(文字列)、number(数値)、boolean(真偽値)の3つです。number は整数と小数を区別せず、どちらも number 型として扱います。
    実行可
  3. 3
    型推論 — 注釈を省略できる場面
    変数を宣言と同時に初期化すると、TypeScript は代入された値から型を自動的に判断します。これを型推論と呼びます。let count = 0 と書けば、注釈がなくても count は number 型になります。
    実行可
  4. 4
    配列の型
    配列の型は、要素の型の後ろに [] を付けて書きます。number[] は数値の配列、string[] は文字列の配列です。Array<number> という書き方もありますが、意味は同じで [] の形が広く使われています。
    実行可
  5. 5
    タプル型
    タプル型は「長さが決まっていて、位置ごとに型が決まっている配列」です。[string, number] と書くと、0番目が文字列、1番目が数値の、要素2つの配列だけを受け付けます。
    実行可
  6. 6
    enum — 名前付きの定数セット
    enum は、関連する定数の集まりに名前を付けてまとめる機能です。enum Direction { Up, Down } のように書き、Direction.Up という形で値を参照します。値を指定しなければ、上から順に 0、1、2 と数値が自動で割り当てられます(数値 enum)。
    実行可
  7. 7
    any — 型チェックをやめる型
    any は「この値の型チェックをやめる」という特別な型です。any 型の値には、どんな値を代入しても、どんなプロパティやメソッドを呼んでもコンパイルエラーになりません。
    実行可
  8. 8
    unknown — 型がまだ分からない値
    unknown は「型がまだ分からない」ことを表す型です。any と同じくどんな値でも入れられますが、決定的な違いとして、型を確かめるまで一切の操作ができません。
    実行可

関数

  1. 9
    関数の引数と戻り値の型
    関数では、各引数の後ろに型注釈を書き、引数リストの閉じカッコの後ろに戻り値の型を書きます。function add(a: number, b: number): number のような形です。
    実行可
  2. 10
    オプション引数とデフォルト値
    引数名の後ろに ? を付けると、その引数は省略できるオプション引数になります。また、引数に = で初期値を書くと、省略されたときにその値が使われるデフォルト値付き引数になります。
    実行可
  3. 11
    rest引数 — 個数が決まらない引数を受け取る
    引数名の前に ... を付けると、その位置以降の引数を何個でもまとめて受け取れる rest引数になります。受け取った値は関数の中で配列になるため、型は ...nums: number[] のように配列の型で書きます。
    実行可
  4. 12
    void — 値を返さない関数
    void は「この関数は値を返さない」ことを表す戻り値専用の型です。ログを出力するだけ、データを保存するだけ、といった return する値がない関数の戻り値に void を書きます。
    実行可
  5. 13
    関数型の書き方 — (x: number) => string
    「関数そのもの」にも型があります。(value: number) => string と書くと「number を1つ受け取り string を返す関数」という型になり、矢印の左に引数、右に戻り値の型を並べます。
    実行可
  6. 14
    関数オーバーロード — 複数の呼び出し方を宣言する
    関数オーバーロードは、1つの関数に複数の呼び出し方を持たせる仕組みです。引数と戻り値だけの宣言(オーバーロードシグネチャ)を上に並べ、最後にすべての呼び出し方を受け止められる実装を1つだけ書きます。
    実行可

オブジェクトの型

  1. 15
    オブジェクトの型
    オブジェクトの型は、プロパティ名と型の組を波カッコで並べて書きます。{ name: string; age: number } のような形で、それぞれのプロパティがどんな型かを指定します。
    実行可
  2. 16
    オプショナルプロパティ ?
    プロパティ名の後ろに ? を付けると「あってもなくてもよい」省略可能なプロパティになります。{ name: string; nickname?: string } なら、nickname のないオブジェクトも代入できます。
    実行可
  3. 17
    readonly プロパティ
    プロパティ名の前に readonly を付けると、そのプロパティは初期化の後に書き換えられなくなります。{ readonly id: number } のように書き、再代入しようとするとコンパイルエラーになります。
    実行可
  4. 18
    interface — オブジェクトの型に名前を付ける
    interface は、オブジェクトの型に名前を付ける宣言です。interface User { name: string; age: number } と一度定義すれば、以降は User という名前だけでその形を指せます。
    実行可
  5. 19
    type エイリアス
    type は、型に別名を付ける宣言です。type Point = { x: number; y: number } のようにオブジェクトの型にも使えますし、type Score = number のようにどんな型にも名前を付けられます。
    実行可
  6. 20
    interface の継承 extends
    interface は extends を使って別の interface を継承できます。interface Dog extends Animal と書くと、Dog は Animal のプロパティをすべて引き継いだうえで、自分のプロパティを追加できます。
    実行可
  7. 21
    インデックスシグネチャ
    インデックスシグネチャは「キーの名前は決まっていないが、キーと値の型は決まっている」オブジェクトを表す書き方です。{ [key: string]: number } と書くと、どんな名前の文字列キーでも値は number、という意味になります。
    実行可
  8. 22
    交差型 & — 型を合成する
    交差型は、複数の型を & でつないで「両方のプロパティをすべて持つ型」を合成する書き方です。type Employee = Identified & Named とすれば、Identified と Named のプロパティを全部備えた型が新しく作れます。
    実行可

ユニオン型と絞り込み

  1. 23
    ユニオン型
    ユニオン型は「複数の型のうちどれか」を表す型で、型と型を | でつないで書きます。string | number は「文字列または数値」という意味になります。
    実行可
  2. 24
    リテラル型
    リテラル型は、特定の値そのものを型にしたものです。"open" という型には文字列 "open" しか入れられません。リテラル型をユニオンで並べた type Direction = "up" | "down" のような形で使うのが定番です。
    実行可
  3. 25
    typeof による絞り込み
    ユニオン型の値は、if 文で typeof を確かめると、そのブロックの中では型が自動的に絞り込まれます。これを絞り込み(narrowing)と呼びます。typeof value === "string" の中では value は string として扱われ、文字列のメソッドが使えるようになります。
    実行可
  4. 26
    in と等価チェックによる絞り込み
    typeof で区別できるのはプリミティブ型だけです。オブジェクト同士のユニオンは、"radius" in shape のように in 演算子で「そのプロパティを持っているか」を確かめて絞り込みます。
    実行可
  5. 27
    instanceof による絞り込み
    instanceof は「その値が特定のコンストラクタから作られたオブジェクトか」を調べる演算子です。value instanceof Date が真になるブロックの中では、value は Date 型に絞り込まれ、日付のメソッドが安全に使えるようになります。
    実行可
  6. 28
    判別可能ユニオン
    判別可能ユニオンは、各メンバーに kind のような共通のリテラル型プロパティ(判別子)を持たせたユニオン型です。state.kind === "success" のように判別子を比較するだけで、そのメンバーの型に正確に絞り込まれます。
    実行可
  7. 29
    型述語 is — 自作の型ガード
    型述語は、自作の関数を絞り込みに使えるようにする仕組みです。関数の戻り値の型の位置に pet is Fish と書くと「この関数が true を返したら pet は Fish 型」とコンパイラに伝わり、if 文でその関数を呼ぶだけで型が絞り込まれます。
    実行可

null安全と特別な型

  1. 30
    null と undefined — strictNullChecks
    TypeScript には「値が無い」ことを表す値が2つあります。null と undefined です。設定ファイルで strictNullChecks を有効にすると、string などの普通の型に null や undefined を入れるとエラーになり、「無いかもしれない」値は string | null のようにユニオン型で明示する決まりになります。
    実行可
  2. 31
    オプショナルチェーン ?.
    ?. は、プロパティにアクセスする . の安全版です。user.nickname?.toUpperCase() のように書くと、手前の値が null か undefined のときはそこで処理が止まり、エラーにならず式全体が undefined になります。値があるときだけ、その先の処理が実行されます。
    実行可
  3. 32
    null合体演算子 ??
    ?? は「左の値が null か undefined のときだけ、右の既定値を使う」演算子です。value ?? 30 と書けば、value に値があればそのまま、無ければ 30 が使われます。「無いかもしれない値に既定値を与える」処理を1行で書けます。
    実行可
  4. 33
    型アサーション as
    as は「この値はこの型だと自分が保証する」とコンパイラに伝える書き方です。value as CityInfo のように書くと、コンパイラの推論を上書きして、その型として扱えるようになります。外部から来たデータなど、コンパイラには分からないが自分は形を知っている、という場面のための機能です。
    実行可
  5. 34
    非nullアサーション !
    値の後ろに ! を付けると「この値は絶対に null や undefined ではない」とコンパイラに宣言できます。findLabel(1)! のように書くと、string | null だった型から null が取り除かれ、string として扱えるようになります。
    実行可
  6. 35
    never — 値が存在しない型
    never は「値が決して存在しない」ことを表す型です。void が「値を返さずに終わる」だったのに対し、never は「正常に終わって値を返すことが決してない」という意味で、必ず例外を throw する関数の戻り値が代表例です。
    実行可
  7. 36
    網羅性チェック — neverで分岐の抜け漏れを防ぐ
    リテラル型のユニオンを switch で分岐するとき、default で値を never 型の変数に代入しておくと、分岐の抜け漏れを検出できます。すべての候補を case で処理していれば default に届く値は存在しないはずなので、never への代入が成立する、という理屈です。
    実行可
  8. 37
    as const — 値をリテラル型で固定する
    const で宣言したオブジェクトでも、プロパティの型は "dark" ではなく string のように広い型に推論されます(これを widening と呼びます)。値の後ろに as const を付けると、この広がりが抑えられ、すべてのプロパティが書いたとおりのリテラル型かつ readonly で固定されます。
    実行可
  9. 38
    satisfies — 型に適合させつつ推論を保つ
    satisfies 演算子は、値が「ある型を満たしているか」を検査しつつ、変数の型は元の具体的な推論結果のまま残す、という両取りを実現します。const config = { ... } satisfies Config と書くと、Config に合っているかはチェックされますが、各プロパティは Config で広げられず、書いた値の具体的な型として使えます。
    実行可

ジェネリクス

  1. 39
    ジェネリック関数
    ジェネリクスは「型を後から決められる」仕組みです。関数名の後ろに <T> と型引数を書き、引数や戻り値の型に T を使います。呼び出すときの値に応じて、T が number や string に決まります。
    実行可
  2. 40
    ジェネリック制約 extends
    型引数に extends を付けると「T は最低限この形を持つ型」という条件を課せます。<T extends { length: number }> と書けば、T は length プロパティを持つ型に限定されます。
    実行可
  3. 41
    ジェネリックな型定義
    関数だけでなく、type や interface にも型引数を持たせられます。type Box<T> = { value: T } と定義すれば、Box<number> や Box<string> のように、中身の型だけ違う型を1つの定義から作れます。
    実行可
  4. 42
    デフォルト型引数 — 型引数に既定値を持たせる
    ジェネリックな型や関数の型引数には、= で既定値を指定できます。type Box<T = string> と書くと、Box とだけ書いたときは T が string とみなされ、Box<number> のように明示すればそちらが使われます。関数の引数にデフォルト値を持たせるのと同じ発想を、型の世界で行うものです。
    実行可
  5. 43
    ジェネリッククラス — 型をパラメータに持つクラス
    クラスにも型引数を持たせられます。class Stack<T> と書くと、中身の型 T を使い手が決められる「型安全な入れ物」を作れます。push する値も pop で取り出す値も T 型として扱われるため、数値用・文字列用のスタックを別々に書かずに、1つの定義から作れます。
    実行可

型の操作

  1. 44
    keyof — キーの一覧を型にする
    keyof は、オブジェクト型からプロパティ名の一覧をユニオン型として取り出す演算子です。keyof User は "name" | "age" | "email" のような、キー名のリテラル型のユニオンになります。
    実行可
  2. 45
    typeof — 値から型を作る
    型を書く場所で typeof を使うと、既存の変数から型を取り出せます。type Settings = typeof defaultSettings と書けば、defaultSettings と同じ形の型が手に入ります。
    実行可
  3. 46
    インデックスアクセス型 — T[K] で型の一部を取り出す
    インデックスアクセス型は、オブジェクト型からプロパティの型を取り出す書き方です。配列の値を arr[0] で取り出すのと同じ感覚で、User["id"] と書くと User の id プロパティの型(number など)が得られます。角括弧の中に書くのは値ではなくリテラル型です。
    実行可
  4. 47
    条件型 — T extends U ? X : Y
    条件型は「T が U に代入できるなら X、できないなら Y」を型のレベルで表す書き方です。三項演算子と同じ形で T extends U ? X : Y と書きます。たとえば IsString<T> を T extends string ? "yes" : "no" と定義すると、渡した型によって結果の型が切り替わります。
    実行可
  5. 48
    infer — 条件型の中で型を取り出す
    infer は条件型の extends 節の中で使い、マッチした型の一部に名前を付けて取り出すキーワードです。T extends (infer E)[] ? E : T と書くと、T が配列なら要素の型を E として捕まえ、結果として返せます。
    実行可
  6. 49
    マップ型 — キーごとに型を作り変える
    マップ型は { [K in keyof T]: ... } という形で、既存の型のキーを1つずつたどりながら新しい型を組み立てる仕組みです。配列の map と同じ発想で、「各キー K に対して値の型をこうする」というルールを書きます。
    実行可
  7. 50
    テンプレートリテラル型と文字列操作型
    テンプレートリテラル型は、文字列のテンプレートリテラルと同じ `...${...}` の構文を型の世界で使う機能です。たとえば type HandlerKey = `on${"Click" | "Hover"}` と書くと "onClick" | "onHover" というユニオン型が生成されます。リテラル型のユニオンを渡すと組み合わせが自動で展開されるのが強力な点です。
    実行可
  8. 51
    Partial と Required
    Partial<T> は、型 T のすべてのプロパティを省略可能(? 付き)に変換するユーティリティ型です。逆に Required<T> は、すべてのプロパティを必須に変換します。
    実行可
  9. 52
    Pick と Omit
    Pick<T, K> は、型 T から指定したプロパティだけを選んで新しい型を作ります。Omit<T, K> はその逆で、指定したプロパティを取り除いた型を作ります。
    実行可
  10. 53
    Record — キーと値の型を決める
    Record<K, V> は「キーが K 型、値が V 型のオブジェクト」を表すユーティリティ型です。Record<string, number> はインデックスシグネチャの { [key: string]: number } と同じ意味を、より短く書けます。
    実行可
  11. 54
    ReturnType と Parameters
    ReturnType<T> は関数型 T の戻り値の型を、Parameters<T> は引数の型をタプルとして取り出すユーティリティ型です。関数そのものから取り出す場合は、typeof と組み合わせて ReturnType<typeof createUser> のように書きます。
    実行可
  12. 55
    Exclude / Extract / NonNullable
    この3つはユニオン型を加工するユーティリティ型です。Exclude<T, U> は T のユニオンから U に当てはまる候補を取り除き、Extract<T, U> は逆に当てはまる候補だけを残します。NonNullable<T> は null と undefined を取り除きます。
    実行可

クラス

  1. 56
    クラスのプロパティとメソッドの型
    クラスでは、プロパティをクラスの先頭で「名前: 型」の形で宣言します。メソッドは通常の関数と同じく、引数と戻り値に型を書きます。コンストラクタの引数にも型注釈を付けます。
    実行可
  2. 57
    アクセス修飾子 public / private / protected
    プロパティやメソッドの前に付けるアクセス修飾子で、どこから触れるかを制限できます。public は どこからでも(省略時の既定)、private はそのクラスの中だけ、protected は継承先のクラスまで、という3段階です。
    実行可
  3. 58
    クラスの継承 extends
    class Dog extends Animal のように extends を使うと、親クラスのプロパティとメソッドをすべて引き継いだクラスを作れます。子クラスに独自のコンストラクタを書く場合は、その先頭で super(...) を呼んで親のコンストラクタを実行するのが決まりです。
    実行可
  4. 59
    abstract — 抽象クラス
    abstract を付けたクラスは「それ自体は new できない、継承されるための土台」になります。abstract を付けたメソッドは名前と型だけを書き、中身は継承した子クラスが必ず実装します。実装し忘れると子クラスの定義時点でエラーになります。
    実行可
  5. 60
    static — インスタンスを作らず使うメンバー
    static を付けたプロパティやメソッドは、インスタンスではなくクラスそのものに属します。new でインスタンスを作らず、IdGenerator.generate() のようにクラス名から直接呼び出します。
    実行可
  6. 61
    implements — インターフェースを実装する
    class Dog implements Greeter のように implements を使うと、「このクラスは interface が定めたプロパティとメソッドを必ず備える」と宣言できます。足りないメンバーがあるとクラスの定義時点でエラーになります。
    実行可
  7. 62
    コンストラクタ引数プロパティ — 宣言と代入の省略記法
    コンストラクタの引数に private などの修飾子を付けると、その引数が自動的に同名のプロパティとして宣言され、値の代入まで行われます。constructor(private repo: UserRepository) {} と書くだけで、プロパティ宣言・引数の受け取り・this.repo = repo の3つが1行にまとまります。
    実行可

モジュールと非同期

  1. 63
    モジュール — import と export
    プログラムが大きくなったら、ファイルを分けて管理します。公開したい関数や型に export を付け、使う側のファイルで import { 名前 } from "./ファイル名" と書いて取り込みます。export や import を持つファイルはモジュールと呼ばれ、export していないものは外のファイルから見えません。
  2. 64
    Promise<T> — 非同期の結果の型
    Promise<T> は「あとで T 型の値が手に入る」ことを表す型です。サーバーへの問い合わせやタイマーのように時間のかかる処理は、結果そのものではなく Promise<string> のような形で返ってきます。中身の値は .then(function (value) { ... }) のコールバックで受け取ります。
    実行可
  3. 65
    async関数の型付け
    関数の前に async を付けると、その関数の戻り値は必ず Promise に包まれます。return firstScore + secondScore と数値を返しても、呼び出し側から見た型は Promise<number> です。async 関数の中では await を使って、Promise の中身を普通の値として取り出せます。
    実行可