TypeScriptのジェネリクスと高度な型操作
TypeScriptのジェネリクスは型を汎用化する強力な機能です。 ユーティリティ型と組み合わせることで、重複のない型安全なコードを書くことができます。
ジェネリクスの基本
function identity<T>(arg: T): T {
return arg;
}
const num = identity<number>(42);
const str = identity("hello"); // 型推論
制約付きジェネリクス
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "田中", age: 25 };
const name = getProperty(user, "name"); // string型
const age = getProperty(user, "age"); // number型
ユーティリティ型
interface User {
id: number;
name: string;
email: string;
}
// 全プロパティをオプショナルに
type PartialUser = Partial<User>;
// 特定のプロパティだけ取り出す
type UserPreview = Pick<User, 'id' | 'name'>;
// 特定のプロパティを除く
type UserWithoutEmail = Omit<User, 'email'>;
// 読み取り専用
type ReadonlyUser = Readonly<User>;
条件型(Conditional Types)
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
// NonNullableの自作
type MyNonNullable<T> = T extends null | undefined ? never : T;
まとめ
ジェネリクスと組み込みユーティリティ型を使いこなすことで、 DRYな型定義が書けます。最初は難しく感じますが、 実際のAPIレスポンス型を定義しながら学ぶのが効果的です。