Genericsの基礎
TypeScript
Genericsとは?
型の決定を遅延できるもの。
基本的には以下のように記述する。
type Foo<T> = {
value: T;
};
const foo: Foo<number> = {
value: 0,
};
Genericsで使用されるTやKなどの由来
Genericsで使用されるTやKなどの由来は以下の通り。
- T:Type
- K:Key
- U:Unknown
- E:Element
以上の4つが慣例的によく使われるので覚えておくと良い。
Genericsの良さ
後から使いまわしたりする際に、型を自由に定義することができる。
type Foo<T> = {
value: T;
};
const foo1: Foo<number> = {
value: 0,
};
const foo2: Foo<string> = {
value: "",
};
const foo3: Foo<number[]> = {
value: [1, 2, 3],
};
Genericsじゃなかったらvalueを定義し直さなければならなくなる。
Genericsのユースケース
以下の例のように後からJapaneseやAmericanの型が決定させたい場合に使われる。
type User<T> = {
name: string;
state: T;
};
type Japanese = User<"東京都" | "大阪府">
type American = User<"CA" | "NY">
const user1: Japanese = {
name: "田中",
state: "東京都",
};
const user2: American = {
name: "taylor",
state:"CA",
};
Genericsの初期値
<T = string>とすることで、初期値がstringとなる。
そのため、foo1でFoo<string>としなくても、初期値はstringだと暗黙的に分かっているので問題ない。
type Foo<T = string> = {
value: T;
};
const foo1: Foo = {
value: "",
};
const foo2: Foo<number> = {
value: 111,
}
Genericsのextendsによる型制約
Genericsの型引数に制約を加えたい時にextendsによる型制約を用いる。
以下のコードだと、extendsでstringを指定しているので、stringに互換性がないnumberはエラーとなる。
type Foo<T extends string> = {
value: T;
};
const foo1: Foo<string> = {
value: "",
};
const foo2: Foo<"abc"> = {
value: "abc",
};
const foo3: Foo<number> = { // 型 'number' は制約 'string' を満たしていません。
value: 123,
};
Genericsの初期値とextendsによる型制約の組み合わせ
シンプルに = string と繋げて記述すればOK。
type Foo<T extends string = string> = {
value: T;
};
const foo1: Foo = {
value: "",
};
const foo2: Foo<"abc"> = {
value: "abc",
};