LoginSignup
0
0

More than 1 year has passed since last update.

TypeScriptのジェネリクスまとめ

Last updated at Posted at 2022-04-22

ジェネリクスとは

型を引数として受け取ることができる。同じ処理を違う型で実行する際に便利。
下記の記事が非常にわかりやすい。

function copy<T>(value: T): T {
    let user: T;
    return value;
}
console.log(copy<string>('hello').toUpperCase);
console.log(copy<number>(6).valueOf);

copy()の引数や戻り値をstringかnumberか指定して実行することができる。

下のようにオブジェクトを引数として取る場合、ジェネリクスを省略してもnameプロパティを使用することができる。
name: stringのオブジェクトだと型推論してくれる。

// 厳密にはこう
console.log(copy<{name: string}>({name: 'Quill'}).name);
// こっちでもOK
console.log(copy({name: 'Quill'}).name);

型パラメータに制約をつける

より厳密に制約を設ける場合はextendsを使用する。

function copy<T extends {name: string}>(value: T): T {
    let user: T;
    return value;
}
console.log(copy({name: 'Quill'}).name);

keyof演算子

keyof演算子を使うことでオブジェクトプロパティのキーのユニオン型を作ることができる

type K = keyof { name: string; age: number }
type K = "name" | "age"
function copy<T extends {name: string}, U extends keyof T>(value: T, key: U): T {
    value[key];
    return value;
}
console.log(copy({ name: 'Quill', age: 38 }, 'name'));

U extends keyof Tは「オブジェクトTのキー」をUとして定義している

クラスへジェネリクスを使用する

class LightDatabase<T extends string | number | boolean> {
    private data: T[] = [];
    get() {
        return this.data;
    }
}
const stringLightDatabase = new LightDatabase<string>();
stringLightDatabase.get();

インターフェースにジェネリクスを使用する

interface TmpDatabase<T> {
    id: number;
    data: T[];
}
const TmpDatabase: TmpDatabase<number> = {
    id: 3,
    data: [32]
}

Utility型

interface Todo {
    title: string;
    text: string;
}
type Todoable = Partial<Todo>
type ReadTodo = Readonly<Todo>
type Todoable = {
    title?: string | undefined;
    text?: string | undefined;
}
type ReadTodo = {
    readonly title: string;
    readonly text: string;
}

配列の型を定義する際はジェネリック型のArrayを使うことができる。
Arrayなどのジェネリック型はTypeScriptに内蔵されている。

const vegetables: Array<string> = ['Tomato', 'Broccoli'];

型パラメータにデフォルト値を設定する

interface ResponseData<T extends { message: string } = any> {
    data: T;
    status: number;
}
let tmp2: ResponseData;

Mapped Types

inを使うことでfor文で型を扱える。
ハイフン-をつけるとVegetablesインターフェースでtomatoに指定していたreadonlyをMappedTypesでは無効化することができる。

interface Vegetables {
    readonly tomato: string;
    pumplin?: string;
}
let tmp3: keyof Vegetables;
type MappedTypes = {
    -readonly [P in keyof Vegetables]?: string
}

Conditional Types

三項演算子のようなものを使用することで型のif文を定義することができる。

type ConditionalTypes = 'tomato' extends string ? number : boolean;
let aa: ConditionalTypes; // number型

type ConditionalTypes2 = string extends 'tomato' ? number : boolean;
let bb: ConditionalTypes2; // boolean型
0
0
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
0
0