メインコンテンツまでスキップ

TypeScript

注記

本書『サバイバルTypeScript』は実務でTypeScriptを使う開発者のための入門書です。そして、このページはTypeScriptの特徴を最速で把握できるよう、数百ページからなる本書のコンテンツをつまみ食いした要約です。

» 本書ついて詳しく知る
» とにかく今すぐTypeScriptを書いてみたい

TypeScriptとは

  • JavaScriptのスーパーセットとなるプログラミング言語。
  • 静的型付け言語であり、プログラムの正しさが静的に検査できる。
  • ライブラリやIDEなどの開発環境が充実しており、大きなエコシステムを持っている。
  • Microsoftが2012年に開発し、オープンソースで公開した。

» TypeScriptの特徴について詳しく知る
» TypeScript誕生の背景について詳しく知る

TypeScriptはJavaScriptのスーパーセット

  • スーパーセットとは、元の言語との互換性を保ちつつ、元の言語を拡張して作った言語のこと。
  • TypeScriptは、JavaScriptとの互換性を保ちつつ、JavaScriptを拡張して作った言語である。
  • よって、JavaScriptのコードはすべてTypeScriptとしてあつかえる。
  • TypeScriptは、型注釈やインターフェース、ジェネリクスなど独自の機能を追加している。
TypeScriptの機能とJavaScriptの機能

スーパーセットのメリット

  • 学習のしやすさ: JavaScriptの知識を活かしてTypeScriptを学べる。
  • 資産が活かせる: 既存のJavaScriptコード資産を活かして開発できる。
  • 移行のしやすさ: 既存のJavaScriptプロジェクトはTypeScriptへ移行がしやすい。

» TypeScriptとJavaScriptの関係について詳しく知る

静的な検査

  • TypeScriptはプログラムの正しさを静的に検査できる。
  • JavaScriptは実行しないとバグがあるかを確かめられない。
  • TypeScriptは実行せずにチェックが行える。

» 静的な検査について詳しく知る

開発効率と品質を向上し、安心感を高める

  • 問題を早期に発見し、開発を効率化できる。
  • コーディング時に問題を発見し、修正できるため、バグを予防できる。
  • エディターとTypeScriptを連携させると、リアルタイムのチェックやコード補完が可能。
エディター上でのフィードバック
  • 問題を早期に修正できることで、製品の信頼感や安心感が高まる。
  • 見通しの悪い大規模なプログラムや、重要なシステムの開発では静的な検査が安心材料になる。

検査の仕組み

  • TypeScriptの検査は型システムに基づく。
  • 型システムに基づき、コンパイルのタイミングでプログラムを検査する。

型システム

  • 型システムは、データの種別ごとに型を与え、データに対して行える操作に制約を設ける。
  • これにより、変数には決められた値のみが代入され、決められた操作のみが行われることが保証され、プログラムが正確で安全になる。
  • 型システムは、数学の「型理論」を背景に構築され、数学的証明によりプログラムの欠陥をあぶり出せる。

型注釈

  • 変数にどのような値が代入できるのかを制約するものを「」と言う。
  • 開発者は、変数がどのような型なのかを型注釈で指定する。
  • TypeScriptでは、型注釈を手がかりに検査が行われる。
型注釈

型推論

  • 値の型が文脈で明白な場合、型が自動で判断される。この仕組みを型推論という。
  • 型推論のおかげで、開発者は型注釈を割愛でき、記述量を減らせる。
型推論

コンパイル

  • TypeScriptを実行するために、JavaScriptへ変換する。この変換のことをコンパイルという。
  • 変換後のJavaScriptコードはブラウザやサーバーで実行できる。
  • TypeScriptの検査はコンパイルのタイミングで行われる。
コンパイル

型はドキュメント、リファクタリング、ツールの充実にも寄与

  • ドキュメントになる: 型情報はドキュメントの役割を果たし、コードの理解を助ける。
  • リファクタリングが安全に: 変数の型や関数のシグネチャを変更したとき、修正が必要な箇所がコンパイル時にすべて分かり、不注意による誤修正を減らせる。
  • ツールサポートが充実: IDEやエディターでのリアルタイムのエラーチェック、自動補完、リファクタリングツール、ナビゲーションなど、開発ツールのサポートが充実している。

» TypeScriptを使う動機について詳しく知る

多くのエディターがTypeScriptをサポート

  • Visual Studio Code
  • JetBrains IDE (IntelliJ, WebStorm, PhpStorm, RubyMine, PyCharm, GoLandなど)
  • Vim
  • NeoVim
  • Emacs (Tide)
  • Atom
  • Sublime Text

» TypeScriptとエコシステムについて詳しく知る

多様なソフトウェアが作れる

作れるものの範囲が広いことは、TypeScriptの魅力のひとつ。

  • Webアプリケーション: TypeScriptの主戦場。フロントエンドの開発に広く使用される。
  • サーバーサイドアプリケーション: Node.jsと組み合わせて、バックエンドやAPIサーバーを開発することが可能。
  • モバイルアプリケーション: React Nativeなどのフレームワークを利用して、モバイルアプリケーションを開発できる。
  • デスクトップアプリケーション: Electronを使用して、クロスプラットフォームのデスクトップアプリを開発できる。
  • クラウド関連の機能: AWS LambdaやAzure Functionsなどのクラウドプラットフォームで、サーバーレス関数が作成できる。
  • ユーティリティーやCLIツール: コマンドラインツールや各種ユーティリティの開発ができる。
  • インフラ構成管理(IaC): PulumiやAWS CDKを使用して、インフラの構成を管理することができる。
  • アプリケーションの拡張機能: Google ChromeやVisual Studio Codeなどデスクトップアプリケーションの拡張をTypeScriptで開発できる。

» TypeScriptの射程圏について詳しく知る

TypeScriptを導入した企業の感想

  • Slack: コードベースが大規模になっても、型システムが安全性と信頼性を保証してくれる。
  • Airbnb: TypeScriptを使っていたらAirbnbの38%ものバグを未然に防げた。
  • ヤフー株式会社: 静的型付けによりコードの品質とメンテナンス性が向上し、IDEとの連携により開発者の生産性が向上した。
  • LINE株式会社: ちょっとした修正でもかかるQAのコストを、TypeScript化によって抑制。
  • Sansan株式会社: 型がドキュメントとしての役割を果たし、コードリーディングや他チームのコード変更に役立った。採用の文脈でアピールポイントにもなった。
  • ラクスル株式会社:型システムの恩恵が得られる、エディターの入力補完を受けられる、コード=ドキュメントという状況を作りやすい。

基本的な型

プリミティブ型

  • boolean: 真偽値。
  • number: 数値。
  • string: 文字列。
  • bigint: 大きな整数。
  • symbol: 一意の値を示す。
  • undefined: 値が定義されていない状態を示す。
  • null: 値が存在しない状態を示す。
typescript
const isReady: boolean = false;
const age: number = 25;
const fullName: string = "John Doe";
const bigNumber: bigint = 100n;
const uniqueSymbol: symbol = Symbol("unique");
const notDefined: undefined = undefined;
const empty: null = null;
typescript
const isReady: boolean = false;
const age: number = 25;
const fullName: string = "John Doe";
const bigNumber: bigint = 100n;
const uniqueSymbol: symbol = Symbol("unique");
const notDefined: undefined = undefined;
const empty: null = null;

特殊な型

  • any: 何でも代入できる型。型が不明な場合に使用する。その値に対する操作の制限がなく、型の安全性は弱まる。
  • unknown: any型と似て、何でも代入できる型。その値に対する操作は制限され、型の安全性が保たれる。
  • void: 値が存在しないことを示す。関数が何も返さない場合に使用する。
  • never: 決して何も返さないことを示す。エラーを投げる関数や無限ループの関数の戻り値として使用する。
typescript
const a: any = 100; // 代入できる
console.log(a * 3); // 操作もできる
300
 
const x: unknown = 100; // 代入はできる
console.log(x * 3); // 操作はできない
'x' is of type 'unknown'.18046'x' is of type 'unknown'.
 
// 戻り値のない関数
function doSomething(): void {}
 
// 戻り値を返すことがありえない関数
function throwError(): never {
throw new Error();
}
typescript
const a: any = 100; // 代入できる
console.log(a * 3); // 操作もできる
300
 
const x: unknown = 100; // 代入はできる
console.log(x * 3); // 操作はできない
'x' is of type 'unknown'.18046'x' is of type 'unknown'.
 
// 戻り値のない関数
function doSomething(): void {}
 
// 戻り値を返すことがありえない関数
function throwError(): never {
throw new Error();
}

型エイリアス

  • 型エイリアスは既存の型を新たな名前で定義する機能。
  • より複雑な型を簡素に表現したり、コードの可読性を向上するのに役立つ。
typescript
type StringOrNumber = string | number;
let value: StringOrNumber;
value = "hello"; // string型が代入可能
value = 123; // number型も代入可能
typescript
type StringOrNumber = string | number;
let value: StringOrNumber;
value = "hello"; // string型が代入可能
value = 123; // number型も代入可能

構造的部分型

  • TypeScriptは構造的部分型を採用している。
  • 構造的部分型では、変数の代入可否を、構造が互換しているかに着目して判定する。
typescript
type Summary = { name: string };
type Detail = { name: string; age: number };
 
const johnDetail: Detail = { name: "John", age: 28 };
const summary: Summary = johnDetail; // 代入できる。構造的部分型として互換があるため
 
const johnSummary: Summary = { name: "John" };
const detail: Detail = johnSummary; // 代入できない。構造的部分型として互換がない(ageを含まないため)
Property 'age' is missing in type 'Summary' but required in type 'Detail'.2741Property 'age' is missing in type 'Summary' but required in type 'Detail'.
typescript
type Summary = { name: string };
type Detail = { name: string; age: number };
 
const johnDetail: Detail = { name: "John", age: 28 };
const summary: Summary = johnDetail; // 代入できる。構造的部分型として互換があるため
 
const johnSummary: Summary = { name: "John" };
const detail: Detail = johnSummary; // 代入できない。構造的部分型として互換がない(ageを含まないため)
Property 'age' is missing in type 'Summary' but required in type 'Detail'.2741Property 'age' is missing in type 'Summary' but required in type 'Detail'.

配列

配列リテラル

  • 配列の値を作るには配列リテラル([])を使う。
  • [要素1, 要素2, ...]の形で配列の初期値を設定できる。
typescript
const numbers = [1, 2, 3];
typescript
const numbers = [1, 2, 3];

配列の型注釈

typescript
let numbers: number[];
let strings: Array<string>;
typescript
let numbers: number[];
let strings: Array<string>;

配列要素へのアクセス

  • 配列要素にアクセスするにはインデックス(インデックス)を使う。
  • 0から始まる整数を指定して配列の値を取得し、代入も可能。
typescript
const colors = ["red", "green", "blue"];
console.log(colors[0]);
'red'
colors[1] = "yellow";
console.log(colors);
['red', 'yellow', 'blue']
typescript
const colors = ["red", "green", "blue"];
console.log(colors[0]);
'red'
colors[1] = "yellow";
console.log(colors);
['red', 'yellow', 'blue']

読み取り専用配列

  • 読み取り専用配列は値の変更ができない配列を表す。
  • 配列の型注釈にreadonlyをつけると読み取り専用配列となる。
  • ReadonlyArray<型名>でも読み取り専用配列が宣言でき、readonly 型名[]と機能は同じ。
typescript
const numbers: readonly number[] = [1, 2, 3];
const strings: ReadonlyArray<string> = ["hello", "world"];
 
numbers[0] = 4; // 値を変更できない
Index signature in type 'readonly number[]' only permits reading.2542Index signature in type 'readonly number[]' only permits reading.
strings.push("!"); // 要素を追加できない
Property 'push' does not exist on type 'readonly string[]'.2339Property 'push' does not exist on type 'readonly string[]'.
typescript
const numbers: readonly number[] = [1, 2, 3];
const strings: ReadonlyArray<string> = ["hello", "world"];
 
numbers[0] = 4; // 値を変更できない
Index signature in type 'readonly number[]' only permits reading.2542Index signature in type 'readonly number[]' only permits reading.
strings.push("!"); // 要素を追加できない
Property 'push' does not exist on type 'readonly string[]'.2339Property 'push' does not exist on type 'readonly string[]'.

配列のループ

typescript
const numbers = [1, 2, 3];
 
for (const num of numbers) {
console.log(num); // 1, 2, 3と出力される
}
typescript
const numbers = [1, 2, 3];
 
for (const num of numbers) {
console.log(num); // 1, 2, 3と出力される
}

タプル型

  • タプル型を使うと、配列の要素数と要素の型が固定される。
  • それぞれの要素のインデックスごとに型が決まる。
typescript
let tuple: [string, number];
tuple = ["hello", 10]; // 代入できる
tuple = [10, "hello"]; // 順序が正しくないため、代入できない
Type 'number' is not assignable to type 'string'.
Type 'string' is not assignable to type 'number'.
2322
2322
Type 'number' is not assignable to type 'string'.
Type 'string' is not assignable to type 'number'.
tuple = ["hello", 10, "world"]; // 要素が多すぎるため代入できない
Type '[string, number, string]' is not assignable to type '[string, number]'. Source has 3 element(s) but target allows only 2.2322Type '[string, number, string]' is not assignable to type '[string, number]'. Source has 3 element(s) but target allows only 2.
typescript
let tuple: [string, number];
tuple = ["hello", 10]; // 代入できる
tuple = [10, "hello"]; // 順序が正しくないため、代入できない
Type 'number' is not assignable to type 'string'.
Type 'string' is not assignable to type 'number'.
2322
2322
Type 'number' is not assignable to type 'string'.
Type 'string' is not assignable to type 'number'.
tuple = ["hello", 10, "world"]; // 要素が多すぎるため代入できない
Type '[string, number, string]' is not assignable to type '[string, number]'. Source has 3 element(s) but target allows only 2.2322Type '[string, number, string]' is not assignable to type '[string, number]'. Source has 3 element(s) but target allows only 2.

タプルの要素へのアクセス

  • タプルの要素にアクセスする場合も配列同様にインデックス(インデックス)を使用する。
typescript
const tuple: [string, number] = ["hello", 10];
console.log(tuple[0]);
'hello'
typescript
const tuple: [string, number] = ["hello", 10];
console.log(tuple[0]);
'hello'

オブジェクト

オブジェクトリテラル

  • オブジェクトの作り方はオブジェクトリテラル({})を使う。
  • { プロパティキー: 値, ... } の形でオブジェクトの初期値を設定できる。
typescript
const john = { name: "John", age: 20 };
typescript
const john = { name: "John", age: 20 };

プロパティアクセス

  • ドット.を使ってオブジェクトのプロパティにアクセスできる。
typescript
console.log(john.name);
'John'
typescript
console.log(john.name);
'John'

オブジェクトの型注釈

typescript
let obj: { name: string; age: number };
typescript
let obj: { name: string; age: number };

readonlyプロパティ

  • readonlyをつけたプロパティは代入できない。
typescript
let obj: { readonly name: string; age: number };
obj = { name: "John", age: 20 };
obj.name = "Tom";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
typescript
let obj: { readonly name: string; age: number };
obj = { name: "John", age: 20 };
obj.name = "Tom";
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.

オプションプロパティー

typescript
let obj: { name: string; age?: number };
obj = { name: "John" }; // `age`プロパティがなくてもエラーにならない
typescript
let obj: { name: string; age?: number };
obj = { name: "John" }; // `age`プロパティがなくてもエラーにならない

オブジェクトメソッド

  • 関数をプロパティに持つオブジェクトを定義できる。
typescript
const obj = {
a: 1,
b: 2,
sum(): number {
return this.a + this.b;
},
};
console.log(obj.sum());
3
typescript
const obj = {
a: 1,
b: 2,
sum(): number {
return this.a + this.b;
},
};
console.log(obj.sum());
3

インデックス型

  • オブジェクトはインデックス型を利用して任意のキーの値を取得することができる。
  • インデックス型プロパティの型注釈は[キー名: プロパティキーの型]: プロパティ値の型 の形で記述する。
typescript
let obj: { [key: string]: number };
obj = { key1: 1, key2: 2 };
console.log(obj["key1"]);
1
console.log(obj["key2"]);
2
typescript
let obj: { [key: string]: number };
obj = { key1: 1, key2: 2 };
console.log(obj["key1"]);
1
console.log(obj["key2"]);
2

Shorthand property names

  • プロパティの値がすでに定義されている変数である場合、そのプロパティ名を省略して記述できる(shorthand property names)。
typescript
const name = "John";
const age = 20;
const obj = { name, age };
console.log(obj);
{ name: 'John', age: 20 }
typescript
const name = "John";
const age = 20;
const obj = { name, age };
console.log(obj);
{ name: 'John', age: 20 }

オプショナルチェーン

  • プロパティが存在するかどうか不確定である場合、?.演算子(オプショナルチェーン)で安全にアクセスできる。
typescript
function printLength(obj: { a?: string }) {
console.log(obj.a?.length);
}
printLength({ a: "hello" });
5
printLength({});
undefined
typescript
function printLength(obj: { a?: string }) {
console.log(obj.a?.length);
}
printLength({ a: "hello" });
5
printLength({});
undefined

Map

Mapオブジェクト

  • Mapオブジェクトはキーとそれに対応する値を対にしたコレクション。
  • キーはオブジェクトも含め任意の値が可能。
typescript
const map = new Map();
map.set("name", "John");
map.set("age", "20");
 
console.log(map.get("name"));
'John'
typescript
const map = new Map();
map.set("name", "John");
map.set("age", "20");
 
console.log(map.get("name"));
'John'

Mapの型注釈

  • Mapの型注釈はMap<キーの型, 値の型>の形で記述する。
typescript
let people: Map<string, number>;
typescript
let people: Map<string, number>;

Mapのループ

  • Mapオブジェクトはfor...ofでループすると、各エントリーがキーと値の配列として順に取得できる。
  • 要素の順序は、要素を追加した順が保証されている。
typescript
for (const [key, value] of map) {
console.log(key, value);
}
typescript
for (const [key, value] of map) {
console.log(key, value);
}

Set

Set オブジェクト

  • Setオブジェクトは同じ値が存在しないコレクション。
  • Setの要素は何でも可能である。
typescript
const set = new Set();
set.add(1);
set.add(2);
set.add(2); // 同じ値は追加されない。
 
console.log(set);
Set {1, 2}
typescript
const set = new Set();
set.add(1);
set.add(2);
set.add(2); // 同じ値は追加されない。
 
console.log(set);
Set {1, 2}

Setの型注釈

  • Setの型注釈はSet<要素の型>の形で記述する。
typescript
let numSet: Set<number>;
typescript
let numSet: Set<number>;

Setのループ

  • SetもMap同様にfor...ofでループすることが可能。
  • 順序はaddした順。
typescript
for (const value of set) {
console.log(value);
}
typescript
for (const value of set) {
console.log(value);
}

列挙型 (Enum)

列挙型の基本

  • 列挙型(enum)は、関連する一連の数値または文字列値の集まりを定義する。
  • 列挙型はenumキーワードを使用して定義する。
typescript
enum Color {
Red,
Green,
Blue,
}
typescript
enum Color {
Red,
Green,
Blue,
}

列挙型に値を設定

  • 列挙体の値は文字列リテラルまたは数値リテラルで指定できる。
typescript
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}
typescript
enum Color {
Red = "red",
Green = "green",
Blue = "blue",
}

列挙型の利用

  • 列挙型の各値にアクセスするにはドット演算子を使用する。
typescript
const myColor: Color = Color.Red;
typescript
const myColor: Color = Color.Red;

ユニオン型

  • ユニオン型は複数の型のうちのいずれかをとる値を表現できる。
  • 型1 | 型2 | ...の形式で使う。
  • ひとつ以上の異なる型の値を同じ変数で扱う場合に使用する。
typescript
let value: boolean | number;
value = true; // 代入できる
value = 100; // 代入できる
typescript
let value: boolean | number;
value = true; // 代入できる
value = 100; // 代入できる

判別可能なユニオン型

  • 判別可能なユニオン型は、共通のリテラル型のプロパティを持つ特別なユニオン型。
  • 共通のプロパティを利用して、型を判別できる。
typescript
type Triangle = { kind: "triangle"; base: number; height: number };
type Rectangle = { kind: "rectangle"; width: number; height: number };
type Shape = Triangle | Rectangle;
 
function getArea(shape: Shape): number {
// 共通のプロパティkindを利用して型を判定する
switch (shape.kind) {
case "triangle":
// この節ではshapeがTriangle型に絞り込まれる
return (shape.base * shape.height) / 2;
case "rectangle":
// この節ではshapeがRectangle型に絞り込まれる
return shape.width * shape.height;
}
}
typescript
type Triangle = { kind: "triangle"; base: number; height: number };
type Rectangle = { kind: "rectangle"; width: number; height: number };
type Shape = Triangle | Rectangle;
 
function getArea(shape: Shape): number {
// 共通のプロパティkindを利用して型を判定する
switch (shape.kind) {
case "triangle":
// この節ではshapeがTriangle型に絞り込まれる
return (shape.base * shape.height) / 2;
case "rectangle":
// この節ではshapeがRectangle型に絞り込まれる
return shape.width * shape.height;
}
}

インターセクション型

  • インターセクション型は複数の型を1つに結合した新しい型を定義する。
  • 型1 & 型2 & ...の形式で使う。
  • その結果として生じた型は、それぞれの型が持つすべてのプロパティとメソッドを備えている。
typescript
type Octopus = { swims: boolean };
type Cat = { nightVision: boolean };
type Octocat = Octopus & Cat;
 
const octocat: Octocat = { swims: true, nightVision: true };
console.log(octocat);
{ swims: true, nightVision: true }
typescript
type Octopus = { swims: boolean };
type Cat = { nightVision: boolean };
type Octocat = Octopus & Cat;
 
const octocat: Octocat = { swims: true, nightVision: true };
console.log(octocat);
{ swims: true, nightVision: true }

分割代入

  • 分割代入を使うと、配列の各要素を一度に変数に代入できる(配列の分割代入)。
typescript
const [a, b] = [1, 2];
console.log(a);
1
console.log(b);
2
typescript
const [a, b] = [1, 2];
console.log(a);
1
console.log(b);
2
typescript
const obj = {
name: "John",
age: 20,
};
 
const { name, age } = obj;
console.log(name);
'John'
console.log(age);
20
typescript
const obj = {
name: "John",
age: 20,
};
 
const { name, age } = obj;
console.log(name);
'John'
console.log(age);
20

条件分岐

  • TypeScriptではJavaScriptと同様に、条件分岐にはif構文やswitch構文が利用できる。

if-else文

typescript
const age: number = 20;
 
if (age >= 20) {
console.log("You are an adult.");
} else {
console.log("You are a minor.");
}
'You are an adult.'
typescript
const age: number = 20;
 
if (age >= 20) {
console.log("You are an adult.");
} else {
console.log("You are a minor.");
}
'You are an adult.'

switch文

typescript
const color: string = "blue";
 
switch (color) {
case "red":
console.log("Color is red.");
break;
case "blue":
console.log("Color is blue.");
break;
default:
console.log("Color is neither red nor blue.");
}
'Color is blue.'
typescript
const color: string = "blue";
 
switch (color) {
case "red":
console.log("Color is red.");
break;
case "blue":
console.log("Color is blue.");
break;
default:
console.log("Color is neither red nor blue.");
}
'Color is blue.'

型の絞り込み

typescript
let value: string | number;
// 50%の確率でstring型またはnumber型の値を代入する
value = Math.random() < 0.5 ? "Hello" : 100;
 
if (typeof value === "string") {
// この節ではvalueはstring型として扱われる
console.log(value.toUpperCase());
} else {
// この節ではvalueはnumber型として扱われる
console.log(value * 3);
}
typescript
let value: string | number;
// 50%の確率でstring型またはnumber型の値を代入する
value = Math.random() < 0.5 ? "Hello" : 100;
 
if (typeof value === "string") {
// この節ではvalueはstring型として扱われる
console.log(value.toUpperCase());
} else {
// この節ではvalueはnumber型として扱われる
console.log(value * 3);
}

関数

  • TypeScriptではアロー関数や関数宣言に型注釈をつけることができる。

アロー関数

typescript
const greet = (name: string): string => {
return `Hello ${name}`;
};
 
console.log(greet("John"));
'Hello John'
typescript
const greet = (name: string): string => {
return `Hello ${name}`;
};
 
console.log(greet("John"));
'Hello John'

関数宣言

typescript
function greet(name: string): string {
return `Hello ${name}`;
}
 
console.log(greet("John"));
'Hello John'
typescript
function greet(name: string): string {
return `Hello ${name}`;
}
 
console.log(greet("John"));
'Hello John'

分割代入引数

  • 関数の引数に配列またはオブジェクトリテラルを展開することができる(分割代入引数)。
typescript
const printCoord = ({ x, y }: { x: number; y: number }) => {
console.log(`Coordinate is (${x}, ${y})`);
};
 
printCoord({ x: 10, y: 20 });
'Coordinate is (10, 20)'
typescript
const printCoord = ({ x, y }: { x: number; y: number }) => {
console.log(`Coordinate is (${x}, ${y})`);
};
 
printCoord({ x: 10, y: 20 });
'Coordinate is (10, 20)'

型ガード関数

  • 特定の型であることを判定する関数(型ガード関数)を利用することで、型が絞り込まれる。
typescript
function isString(value: any): value is string {
return typeof value === "string";
}
 
function printLength(value: any) {
if (isString(value)) {
// この節ではvalueはstring型として扱われる
console.log(value.length);
}
}
 
printLength("hello");
5
typescript
function isString(value: any): value is string {
return typeof value === "string";
}
 
function printLength(value: any) {
if (isString(value)) {
// この節ではvalueはstring型として扱われる
console.log(value.length);
}
}
 
printLength("hello");
5

オプション引数

typescript
function greet(name?: string) {
if (name === undefined) {
return "Hello!";
} else {
return `Hello ${name}!`;
}
}
 
console.log(greet("John"));
'Hello John!'
console.log(greet());
'Hello!'
typescript
function greet(name?: string) {
if (name === undefined) {
return "Hello!";
} else {
return `Hello ${name}!`;
}
}
 
console.log(greet("John"));
'Hello John!'
console.log(greet());
'Hello!'

デフォルト引数

  • 関数の引数には=を使ってデフォルトの値を設定することができる(デフォルト引数)。
typescript
function greet(name: string = "Mystery") {
return `Hello ${name}!`;
}
 
console.log(greet("John"));
'Hello John!'
console.log(greet());
'Hello Mystery!'
typescript
function greet(name: string = "Mystery") {
return `Hello ${name}!`;
}
 
console.log(greet("John"));
'Hello John!'
console.log(greet());
'Hello Mystery!'

残余引数

  • ...を使って残余引数(任意の数の引数)を設定することができる。
typescript
function sum(...numbers: number[]) {
return numbers.reduce((total, num) => total + num, 0);
}
 
console.log(sum(1, 2, 3, 4, 5));
15
typescript
function sum(...numbers: number[]) {
return numbers.reduce((total, num) => total + num, 0);
}
 
console.log(sum(1, 2, 3, 4, 5));
15

クラス

クラス構文

  • JavaScriptのクラス構文はそのまま利用できる。
  • フィールド宣言に型注釈をつけることができる。
typescript
class Person {
name: string;
age: number;
 
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
john.introduce();
'My name is John and I am 20 years old.'
typescript
class Person {
name: string;
age: number;
 
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
john.introduce();
'My name is John and I am 20 years old.'

アクセス修飾子

typescript
class Person {
public name: string;
private age: number;
 
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
console.log(john.name); // 'John'が出力される
console.log(john.age); // エラー(privateなのでアクセスできない)
Property 'age' is private and only accessible within class 'Person'.2341Property 'age' is private and only accessible within class 'Person'.
typescript
class Person {
public name: string;
private age: number;
 
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
console.log(john.name); // 'John'が出力される
console.log(john.age); // エラー(privateなのでアクセスできない)
Property 'age' is private and only accessible within class 'Person'.2341Property 'age' is private and only accessible within class 'Person'.

クラスのreadonly修飾子

  • readonly修飾子をつけたプロパティは、読み取り専用となる。
  • readonly修飾子はアクセス修飾子と併用可能。
typescript
class Person {
readonly name: string;
private readonly age: number;
 
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
john.name = "Tom"; // エラー(readonlyのため変更不可)
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.
typescript
class Person {
readonly name: string;
private readonly age: number;
 
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
john.name = "Tom"; // エラー(readonlyのため変更不可)
Cannot assign to 'name' because it is a read-only property.2540Cannot assign to 'name' because it is a read-only property.

Constructor shorthand

  • TypeScriptでは、コンストラクタパラメータにアクセス修飾子をつけることで、自動的にそのフィールドが定義される(constructor shorthand)。
  • これによりコードの簡略化が図れる。
typescript
class Person {
constructor(public name: string, private age: number) {}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
john.introduce();
'My name is John and I am 20 years old.'
typescript
class Person {
constructor(public name: string, private age: number) {}
 
introduce(): void {
console.log(`My name is ${this.name} and I am ${this.age} years old.`);
}
}
 
const john = new Person("John", 20);
john.introduce();
'My name is John and I am 20 years old.'

フィールドの初期化子

typescript
class Counter {
count = 0; // 初期値を0に設定
// ^^^初期化子
 
increment(): void {
this.count++;
}
}
 
const counter = new Counter();
console.log(counter.count);
0
counter.increment();
console.log(counter.count);
1
typescript
class Counter {
count = 0; // 初期値を0に設定
// ^^^初期化子
 
increment(): void {
this.count++;
}
}
 
const counter = new Counter();
console.log(counter.count);
0
counter.increment();
console.log(counter.count);
1

静的フィールドと静的メソッド

  • staticキーワードを使うことで、インスタンスではなくクラス自体に関連するフィールドやメソッドを定義できる(静的フィールド静的メソッド)。
typescript
class MyClass {
static x = 0;
 
static printX(): void {
console.log(MyClass.x);
}
}
 
MyClass.printX();
0
typescript
class MyClass {
static x = 0;
 
static printX(): void {
console.log(MyClass.x);
}
}
 
MyClass.printX();
0

this型

  • メソッド内でthisを返すことで、メソッドの呼び出しを直列につなげるメソッドチェーンを可能にする(メソッドチェーン)。
typescript
class MyClass {
value = 1;
 
increment(): this {
this.value++;
return this;
}
 
add(v: number): this {
this.value += v;
return this;
}
 
print(): this {
console.log(this.value);
return this;
}
}
 
new MyClass().increment().add(3).print();
5
typescript
class MyClass {
value = 1;
 
increment(): this {
this.value++;
return this;
}
 
add(v: number): this {
this.value += v;
return this;
}
 
print(): this {
console.log(this.value);
return this;
}
}
 
new MyClass().increment().add(3).print();
5

クラスの継承

  • extendsキーワードにより、クラスの継承が可能。
  • スーパークラスのプロパティ・メソッドの値は、サブクラスからアクセス可能。
typescript
class Animal {
name: string;
 
constructor(name: string) {
this.name = name;
}
 
greet(): string {
return `Hello, my name is ${this.name}`;
}
}
 
class Dog extends Animal {
bark(): string {
return "Woof!";
}
}
 
const dog = new Dog("Max");
console.log(dog.greet());
'Hello, my name is Max'
console.log(dog.bark());
'Woof!'
typescript
class Animal {
name: string;
 
constructor(name: string) {
this.name = name;
}
 
greet(): string {
return `Hello, my name is ${this.name}`;
}
}
 
class Dog extends Animal {
bark(): string {
return "Woof!";
}
}
 
const dog = new Dog("Max");
console.log(dog.greet());
'Hello, my name is Max'
console.log(dog.bark());
'Woof!'

instanceof演算子

  • instanceof演算子は、オブジェクトが特定のクラスのインスタンスであるかを判定できる。
typescript
class Animal {}
class Dog extends Animal {}
 
const dog = new Dog();
 
console.log(dog instanceof Dog);
true
console.log(dog instanceof Animal);
true
typescript
class Animal {}
class Dog extends Animal {}
 
const dog = new Dog();
 
console.log(dog instanceof Dog);
true
console.log(dog instanceof Animal);
true

抽象クラス

  • abstractキーワードにより、抽象クラスを定義できる。
  • 抽象クラスはインスタンス化できず、他のクラスが継承するための基底クラスに使用される。
typescript
abstract class Animal {
abstract makeSound(): void;
 
move(): void {
console.log("roaming the earth...");
}
}
 
class Dog extends Animal {
makeSound(): void {
console.log("Woof Woof");
}
}
 
const dog = new Dog();
dog.move();
'roaming the earth...'
dog.makeSound();
'Woof Woof'
typescript
abstract class Animal {
abstract makeSound(): void;
 
move(): void {
console.log("roaming the earth...");
}
}
 
class Dog extends Animal {
makeSound(): void {
console.log("Woof Woof");
}
}
 
const dog = new Dog();
dog.move();
'roaming the earth...'
dog.makeSound();
'Woof Woof'

ゲッターとセッター

  • ゲッターやセッターは、オブジェクトのプロパティを取得・設定するためのメソッド。
  • ゲッターはgetキーワードで、セッターはsetキーワードで定義する。
typescript
class Circle {
private _radius: number;
 
constructor(radius: number) {
this._radius = radius;
}
 
// ゲッター
get radius(): number {
return this._radius;
}
 
// セッター
set radius(radius: number) {
if (radius <= 0) {
throw new Error("Invalid radius value");
}
this._radius = radius;
}
}
 
const circle = new Circle(5);
console.log(circle.radius);
5
circle.radius = 3;
console.log(circle.radius);
3
circle.radius = -2;
// 例外: 'Invalid radius value'
typescript
class Circle {
private _radius: number;
 
constructor(radius: number) {
this._radius = radius;
}
 
// ゲッター
get radius(): number {
return this._radius;
}
 
// セッター
set radius(radius: number) {
if (radius <= 0) {
throw new Error("Invalid radius value");
}
this._radius = radius;
}
}
 
const circle = new Circle(5);
console.log(circle.radius);
5
circle.radius = 3;
console.log(circle.radius);
3
circle.radius = -2;
// 例外: 'Invalid radius value'

インターフェース

  • TypeScriptのインターフェースは、プロパティ、メソッド、クラスなどの形状を定義する能力を持つ。
  • インターフェースを使用する主な目的は、特定のクラスまたはオブジェクトが特定のプロパティまたはメソッドを保持することを強制する。
typescript
interface Printable {
print(): void;
}
 
class MyClass implements Printable {
print(): void {
console.log("Hello, world!");
}
}
typescript
interface Printable {
print(): void;
}
 
class MyClass implements Printable {
print(): void {
console.log("Hello, world!");
}
}

インターフェース構文

  • TypeScriptのインターフェースはオブジェクトの形状を定義することが可能。
  • インターフェースはプロパティやメソッドのシグネチャを記述できる。
typescript
interface Point {
readonly x: number;
readonly y: number;
sum(): number;
}
 
const point: Point = {
x: 10,
y: 20,
sum: function () {
return this.x + this.y;
},
};
typescript
interface Point {
readonly x: number;
readonly y: number;
sum(): number;
}
 
const point: Point = {
x: 10,
y: 20,
sum: function () {
return this.x + this.y;
},
};

インターフェースのreadonly修飾子

  • インターフェース内でreadonly修飾子を使用して、プロパティを読み取り専用に設定できる。
  • これにより、プロパティの値が一旦設定されると後から変更できなくなる。
typescript
interface Point {
readonly x: number;
readonly y: number;
}
 
const p1: Point = { x: 10, y: 20 };
p1.x = 5;
Cannot assign to 'x' because it is a read-only property.2540Cannot assign to 'x' because it is a read-only property.
typescript
interface Point {
readonly x: number;
readonly y: number;
}
 
const p1: Point = { x: 10, y: 20 };
p1.x = 5;
Cannot assign to 'x' because it is a read-only property.2540Cannot assign to 'x' because it is a read-only property.

例外処理

  • TypeScriptでは例外処理のためにtry / catch / finally ブロックを使用できる。
  • 例外が発生した場合(つまり、エラーオブジェクトをスローした場合)catchブロックが実行される。
typescript
try {
throw new Error("An error occurred!");
} catch (error) {
console.log(error);
}
typescript
try {
throw new Error("An error occurred!");
} catch (error) {
console.log(error);
}

try-catch-finally構文

  • tryブロック内のコードは、エラーを検出し、catchブロックはエラーをハンドリングする。
  • finallyブロックはエラーの有無に関係なく実行される。
typescript
try {
throw new Error("Oops, something went wrong.");
} catch (error) {
console.log(error);
} finally {
console.log("This is the finally block. It always gets executed.");
}
typescript
try {
throw new Error("Oops, something went wrong.");
} catch (error) {
console.log(error);
} finally {
console.log("This is the finally block. It always gets executed.");
}

例外クラス

  • TypeScriptでは、カスタムエラークラスを作成することも可能。
  • Errorクラスを継承したカスタムクラスで、具体的なエラータイプを作成することができる。
typescript
class CustomError extends Error {
code = "CustomError";
 
constructor(message?: string) {
super(message);
}
}
 
try {
throw new CustomError("This is a custom error");
} catch (error) {
if (error instanceof CustomError) {
console.log(`${error.code}: ${error.message}`);
}
}
typescript
class CustomError extends Error {
code = "CustomError";
 
constructor(message?: string) {
super(message);
}
}
 
try {
throw new CustomError("This is a custom error");
} catch (error) {
if (error instanceof CustomError) {
console.log(`${error.code}: ${error.message}`);
}
}

非同期処理

  • TypeScriptでは、非同期プログラミングをサポートしていて、コード内で時間を要する処理を効率的に扱うことができる。

Promise

  • Promiseは非同期操作の最終的な完了(または失敗)とその結果の値を表す。
typescript
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Promise resolved");
}, 2000);
});
 
promise.then((data) => {
console.log(data);
});
'Promise resolved'
typescript
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Promise resolved");
}, 2000);
});
 
promise.then((data) => {
console.log(data);
});
'Promise resolved'

async/await 構文

  • 非同期処理をより直感的に書くことができるasync構文await構文を導入している。
  • async/await 構文を使うと、非同期コードをあたかも同期コードであるかのように書ける。
typescript
function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
 
async function asyncFunction() {
console.log("Start");
await delay(2000);
console.log("End");
}
 
asyncFunction();
 
'Start'
// 2秒後
'End'
typescript
function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
 
async function asyncFunction() {
console.log("Start");
await delay(2000);
console.log("End");
}
 
asyncFunction();
 
'Start'
// 2秒後
'End'

ジェネリクス

  • TypeScriptのジェネリクスを使用すると、型の再利用性が向上し、型の一貫性を保つことができる。
  • ジェネリクスを使用すると、型変数を導入でき、これにより機能の一部を一般化できる。
typescript
// Tが型変数
function identity<T>(arg: T): T {
return arg;
}
 
// 型変数Tにstringを割り当てる
const output1 = identity<string>("myString");
const output1: string
 
// 型変数Tにnumberを割り当てる
const output2 = identity<number>(100);
const output2: number
typescript
// Tが型変数
function identity<T>(arg: T): T {
return arg;
}
 
// 型変数Tにstringを割り当てる
const output1 = identity<string>("myString");
const output1: string
 
// 型変数Tにnumberを割り当てる
const output2 = identity<number>(100);
const output2: number

モジュール

  • TypeScriptのモジュールシステムは、他のモジュールと共有するコードと、モジュール内部限定のコードとを分けることを可能にする(モジュール)。
greeter.ts
typescript
export function greet(name: string) {
return `Hello, ${name}!`;
}
greeter.ts
typescript
export function greet(name: string) {
return `Hello, ${name}!`;
}
main.ts
typescript
import { greet } from "./greeter";
console.log(greet("TypeScript"));
'Hello, TypeScript!'
main.ts
typescript
import { greet } from "./greeter";
console.log(greet("TypeScript"));
'Hello, TypeScript!'

importとexport

  • モジュール内で定義した関数や変数を外部に公開するには、exportを使用する。
  • モジュールが公開した関数や変数を利用するには、importを使用する。
math.ts
typescript
export function square(x: number) {
return x * x;
}
 
export function cube(x: number) {
return x * x * x;
}
math.ts
typescript
export function square(x: number) {
return x * x;
}
 
export function cube(x: number) {
return x * x * x;
}
main.ts
typescript
import { square, cube } from "./math";
 
console.log(square(2));
4
console.log(cube(2));
8
main.ts
typescript
import { square, cube } from "./math";
 
console.log(square(2));
4
console.log(cube(2));
8

default export

  • defaultキーワードを使用すると、モジュールがデフォルトで1つの値のみをエクスポートすることを意味する。
  • default exportは、importする際に別名を指定することが可能である。
greeter.ts
typescript
export default function greet(name: string) {
return `Hello, ${name}!`;
}
greeter.ts
typescript
export default function greet(name: string) {
return `Hello, ${name}!`;
}
main.ts
typescript
import greetFunction from "./greeter";
console.log(greetFunction("TypeScript"));
'Hello, TypeScript!'
main.ts
typescript
import greetFunction from "./greeter";
console.log(greetFunction("TypeScript"));
'Hello, TypeScript!'

再export

  • モジュールは、別のモジュールからエクスポートされたものを再エクスポートすることができる。
math.ts
typescript
export function add(x: number, y: number) {
return x + y;
}
math.ts
typescript
export function add(x: number, y: number) {
return x + y;
}
index.ts
typescript
// 再エクスポート
export { add } from "./math";
index.ts
typescript
// 再エクスポート
export { add } from "./math";
main.ts
typescript
import { add } from "./index";
console.log(add(2, 3));
5
main.ts
typescript
import { add } from "./index";
console.log(add(2, 3));
5

type importとtype export

  • 型だけをエクスポート・インポートすることもできる。
types.ts
typescript
export type MyObject = {
name: string;
age: number;
};
types.ts
typescript
export type MyObject = {
name: string;
age: number;
};
main.ts
typescript
import type { MyObject } from "./types";
// ^^^^型インポート
 
const obj: MyObject = {
name: "TypeScript",
age: 3,
};
main.ts
typescript
import type { MyObject } from "./types";
// ^^^^型インポート
 
const obj: MyObject = {
name: "TypeScript",
age: 3,
};

型レベルプログラミング

  • TypeScriptには、typeof演算子やkeyof演算子、ユーティリティータイプなど、型レベルでプログラミングをするためのさまざまな機能が搭載されている。

typeof型演算子

typescript
const object = {
name: "TypeScript",
version: 3.9,
};
 
type ObjectType = typeof object;
type ObjectType = { name: string; version: number; }
typescript
const object = {
name: "TypeScript",
version: 3.9,
};
 
type ObjectType = typeof object;
type ObjectType = { name: string; version: number; }

keyof型演算子

  • keyof演算子を使うと、object型のすべてのキーを文字列リテラルのユニオン型として取得できる。
typescript
type Point = {
x: number;
y: number;
};
 
type Key = keyof Point;
type Key = keyof Point
const key1: Key = "x"; // 代入OK
const key2: Key = "y"; // 代入OK
const key3: Key = "z"; // 代入不可
Type '"z"' is not assignable to type 'keyof Point'.2322Type '"z"' is not assignable to type 'keyof Point'.
typescript
type Point = {
x: number;
y: number;
};
 
type Key = keyof Point;
type Key = keyof Point
const key1: Key = "x"; // 代入OK
const key2: Key = "y"; // 代入OK
const key3: Key = "z"; // 代入不可
Type '"z"' is not assignable to type 'keyof Point'.2322Type '"z"' is not assignable to type 'keyof Point'.

ユーティリティ型

  • TypeScriptは、既存の型から新しい型を作成するためのさまざまな一般的な型操作を提供している。

Required

  • Requiredは、オプションプロパティーを必須プロパティーにするユーティリティ型。
typescript
type Person = {
name: string;
age?: number;
};
 
type RequiredPerson = Required<Person>;
type RequiredPerson = { name: string; age: number; }
// ageがオプションでなくなっている点に注目
typescript
type Person = {
name: string;
age?: number;
};
 
type RequiredPerson = Required<Person>;
type RequiredPerson = { name: string; age: number; }
// ageがオプションでなくなっている点に注目

Partial

  • Partialは、型のすべてのプロパティをオプションにするユーティリティ型。
typescript
type Person = {
name: string;
age: number;
};
 
type OptionalPerson = Partial<Person>;
type OptionalPerson = { name?: string | undefined; age?: number | undefined; }
typescript
type Person = {
name: string;
age: number;
};
 
type OptionalPerson = Partial<Person>;
type OptionalPerson = { name?: string | undefined; age?: number | undefined; }

Readonly

  • Readonlyは、型のすべてのプロパティをreadonlyにするユーティリティ型。それらのプロパティは再代入できない。
typescript
type Person = {
name: string;
age: number;
};
 
type ReadonlyPerson = Readonly<Person>;
type ReadonlyPerson = { readonly name: string; readonly age: number; }
typescript
type Person = {
name: string;
age: number;
};
 
type ReadonlyPerson = Readonly<Person>;
type ReadonlyPerson = { readonly name: string; readonly age: number; }

Record

  • Recordは、オブジェクトのすべてのプロパティ値を特定の型に設定するユーティリティ型。
typescript
type ThreeLetterRecord = Record<"one" | "two" | "three", string>;
type ThreeLetterRecord = { one: string; two: string; three: string; }
typescript
type ThreeLetterRecord = Record<"one" | "two" | "three", string>;
type ThreeLetterRecord = { one: string; two: string; three: string; }

Pick

  • Pickは、オブジェクトから特定のプロパティだけを拾い出すユーティリティ型。
typescript
type Person = {
name: string;
age: number;
address: string;
};
 
type PersonNameAndAge = Pick<Person, "name" | "age">;
type PersonNameAndAge = { name: string; age: number; }
typescript
type Person = {
name: string;
age: number;
address: string;
};
 
type PersonNameAndAge = Pick<Person, "name" | "age">;
type PersonNameAndAge = { name: string; age: number; }

Omit

  • Omitは、オブジェクトから特定のプロパティを省いた型を作るユーティリティ型。
typescript
type Person = {
name: string;
age: number;
address: string;
};
 
type PersonWithoutAddress = Omit<Person, "address">;
type PersonWithoutAddress = { name: string; age: number; }
typescript
type Person = {
name: string;
age: number;
address: string;
};
 
type PersonWithoutAddress = Omit<Person, "address">;
type PersonWithoutAddress = { name: string; age: number; }

Exclude

  • Excludeは、ユニオン型から特定の型を除外するユーティリティ型。
typescript
type T1 = number | string | boolean;
type T2 = Exclude<T1, boolean>;
type T2 = string | number
typescript
type T1 = number | string | boolean;
type T2 = Exclude<T1, boolean>;
type T2 = string | number

Extract

  • Extractは、ふたつのユニオン型の共通の部分を抽出するユーティリティ型。
typescript
type T1 = number | string | boolean;
type T2 = string | boolean;
type T3 = Extract<T1, T2>;
type T3 = string | boolean
typescript
type T1 = number | string | boolean;
type T2 = string | boolean;
type T3 = Extract<T1, T2>;
type T3 = string | boolean

NonNullable

  • NonNullableは、nullまたはundefinedを含む型からいずれも除外するユーティリティ型。
typescript
type T1 = string | null | undefined;
type T2 = NonNullable<T1>;
type T2 = string
typescript
type T1 = string | null | undefined;
type T2 = NonNullable<T1>;
type T2 = string

Mapped types

  • Mapped typesを使うと、既存の型から新しい型を生成できる。
  • Mapped typesは、オブジェクトの各プロパティを”マップ”し、新しいオブジェクトを生成する。
typescript
type Person = {
name: string;
age: number;
};
 
type ReadOnlyPerson = { readonly [K in keyof Person]: Person[K] };
type ReadOnlyPerson = { readonly name: string; readonly age: number; }
typescript
type Person = {
name: string;
age: number;
};
 
type ReadOnlyPerson = { readonly [K in keyof Person]: Person[K] };
type ReadOnlyPerson = { readonly name: string; readonly age: number; }

インデックスアクセス型

typescript
type Person = {
name: string;
age: number;
};
 
type Name = Person["name"];
type Name = string
typescript
type Person = {
name: string;
age: number;
};
 
type Name = Person["name"];
type Name = string