Halcyon Days

IT × 移住 × ファイナンス

MENU

型嫌いから卒業するためにTypeScriptの型をまとめてみた

「型がわかんねぇ」から卒業したい

これまでPHPPythonなど動的型付言語しか扱ってこなかったのであまり型について意識してこなかった。

はじめてJavaに触れたときは、型注釈が書かれていることへの強烈な違和感と気持ち悪さを感じたのを今でも覚えている(若干トラウマ)。

しかし、業務でTypeScriptに触れることになり、否が応でも静的型付言語に慣れなければならなくなったので、これを機に型と友達になろうと思う。

TypeScriptの型

TypeScriptには下記の型がある。

  • boolean
  • number
  • string
  • Array
  • Object
  • tuple
  • enum
  • any
  • Union
  • Literal
  • function
  • void
  • unknown
  • never
  • null
  • undefined

型注釈と型推論、それからいくつもある型の中から何個かピックアップして解説する。

型注釈

制作者側で型を指定するときは下記のように書く。

const result: number = 1 + 1;

型推論

型注釈を省略するとプログラム側で型を自動で決めてくれる。

const greeting = "Hello";
console.log(typeof greeting); // string

オブジェクトにおける型注釈と型推論

型注釈

オブジェクトに対して型注釈をつけたい場合は下記のようにする。

const student: {
    name: string;
    grade: number;
    classroom: number;
} = {
    name: "John",
    grade: 1,
    classroom: 2,
};

型推論

型推論で書きたい場合は下記のようにする。

const student = {
    name: "John",
    grade: 1,
    classroom: 2,
};

配列における型注釈

配列に型を付けたい場合は下記のようにする。

const subject: string[] = ["Japanse", "Math", "English"];

上記の例の場合、配列に格納される値の型はすべてstring型でなければならず、別の型の値を入れるとエラーが発生する。

複数の型を配列に使いたい場合

複数の型の値、たとえばstring型とnumber型など、を配列に格納したい場合は、

を使うと実現できる。

// 型推論
const menu = ["salad", 750];

// Union型
const menu: (string | number)[] = ["crepe" 600];

// any型
const menu: any[] = ["apple juice", 250, true];

上記の例だと型推論とUnion型は同じ意味になるが、どのインデックスに何が入るのか決まっているのであればtuple型にしたほうがいいかも。

any型はなんでも入れることができてしまう(=エラーにつながりやすい)ので、できれば使わないほうが吉。

tuple型

複数の値を保持できる点は配列と似ているが、それぞれのインデックスに対して入る値の型を決められるのが配列との違い。

型注釈で書くと下記のようになる。

const foods: [string, number, number, boolean] = ["rice", 150, 200, false];

各インデックスに対して異なる型の値を入れる、たとえば ”rice” の場所に 0 を入れるとエラーが発生する。

より厳格に複数の値を保持したいのであればtupleを使う。

enum

定数に名前を付けたい場合はenum型を使う。

enum SchoolCategory {
    EREMENTARY = 'EREMENTARY',
    JUNIORHIGH = 'JUNIORHIGH',
    HIGH = 'HIGH',
    UNIVERSITY = 'UNIVERSITY'
}

const Student = {
    finalAcademicBackground: SchoolCategory.UNIVERSITY,
    graduation: false
}

Union型

配列のトピックでも少し触れたが、複数の型を使いたい場合に使う。

let result: number | boolean = 1 + 1;

result = false;
result = 2;

// 配列の場合
let result: (number | boolean)[] = [1, false];

Literal型

特定の値のみ受け入れたい場合に使う。

let success: 'success' = 'success';

この場合は、 success 以外の値は入れられなくなる。

型推論const を使うとLiteral型になる。

const success = 'success';

複数文字列のみ受け付けるようにしたい場合は下記のようにする。

let fiveElements: 'wood' | 'fire' | 'earth' | 'metal' | 'water' = 'wood';

Typeエイリアス

Typeエイリアスを使うと型を変数のように扱うことができる。

type Subject = 'Japanese' | 'Math' | 'Science'
let subject: Subject = 'Japanese';

関数の型

関数は仮引数と戻り値に型を適用させる。

function greeting(greet: string, name: string): string {
    return greet + "!, " + name;
} 

ここでは () 内に引数の型を、() のあとに戻り値の型を書く。

アロー関数の場合は下記のように書く。

const result = (num: number): number => num / 2

const result: (num: number) => number = num => num / 2

コールバック関数の場合

コールバック関数の型注釈は下記のようにする。

function processNumbers(numbers: number[], callback: (num: number) => number): number[] {
  return numbers.map(callback);
}

const double = (num: number): number => {
  return num * 2;
};

callback: (num: number) => number 部分がコールバック関数の型注釈。

void型

関数が明示的に何も返さないときに使う。

つまり、戻り値がないことを意味するのがvoid型。

never型

決して何も返したくない時に使う。

例外を投げるときや無限ループを実行するときに使う。

function error(errMsg: string): never {
    throw new Error(errMsg);
}

function loop(): never {
    while(true) {
        // 無限ループの処理
    }
}

参照ドキュメント