KINTO Tech Blog
Frontend

TypeScript入門

Ren.M
Ren.M
Cover Image for TypeScript入門

はじめに

こんにちは!
KINTO テクノロジーズ プロジェクト推進 G の Ren.M です。
私は普段、KINTO ONE(中古車)のフロントエンド開発をしています。
今回は TypeScript の基礎である型定義についてご紹介させていただきます。

この記事の対象者

  • TypeScript の型定義について学びたい方
  • JavaScript の次に TypeScript を学びたい方

TypeScript とは

そもそも TypeScript とは JavaScript を拡張した言語になります。
そのため JavaScript と同様の構文が使えます。
従来の JavaScript ではデータ型の宣言が不要である種自由にプログラムを記述することができました。
しかしプログラムの品質向上などが求められ、型の不一致などを防ぐ必要があります。
そこで静的型付けを用いる TypeScript が使用されるようになりました。
型定義について理解することでスムーズにコーディングができ安全なデータに受け渡しをすることができます。

JavaScript との違い

JavaScript では以下のデータ型の異なる代入が可能です。

let value = 1;
value = "Hello";

しかし TypeScript では以下ような挙動になります。

let value = 1;

// number型でないため代入不可
value = "Hello";

// 同じnumber型のため代入可能
value = 2;

主なデータ型の種類

// string型
const name: string = "Taro";

// number型
const age: number = 1;

// boolean型
const flg: boolean = true;

// array string型
const array: string[] = ["apple", "banana", "grape"];

:の後に型を明示的に定義することを「型アノテーション」と呼びます。

型推論

TypeScript では上記のように型アノテーションを使わなくても自動で型をつけてくれます。
これを型推論といいます。

let name = "Taro"; // string型

// Bad:nameはstring型のため代入できない
name = 1;

// Good:string型のため代入できる
name = "Ken";

配列の型定義

// number型のみ許容する配列
const arrayA: number[] = [1, 2, 3];

// number型 or string型のみ許容する配列
const arrayB: (number | string)[] = [1, 2, "hoge"];

interface

オブジェクトの型定義は interface を使用できます。

interface PROFILE {
  name: string;
  age?: number;
}

const personA: PROFILE = {
  name: "Taro",
  age: 22,
};

上記のageのようにキー要素に後ろに「?」を付与することでプロパティを任意にすることもできます。

// 'age'要素がなくてもOK
const personB: PROFILE = {
  name: "Kenji",
};

Intersection Types

複数の型を結合したものを Intersection Types と言います。
下記だとSTAFFが該当します。

type PROFILE = {
  name: string;
  age: number;
};

type JOB = {
  office: string;
  category: string;
};

type STAFF = PROFILE & JOB;

const personA: STAFF = {
  name: "Jiro",
  age: 29,
  office: "Tokyo",
  category: "Engineer",
};

Union Types

|(パイプ)を用いることで 2 つ以上の型を定義することができます。

let value: string | null = "text";

// Good
value = "kinto";

// Good
value = null;

// Bad
value = 1;

配列の場合

let arrayUni: (number | null)[];

// Good
arrayUni = [1, 2, null];

// Bad
arrayUni = [1, 2, "kinto"];

Literal Types

代入可能な値を明示的に型にすることもできます。

let fruits: "apple" | "banana" | "grape";

// Good
fruits = "apple";

// Bad
fruits = "melon";

typeof

宣言済みの変数などから型を継承したい場合は typeof を使います。

let message: string = "Hello";

// messageのstring型を継承
let newMessage: typeof message = "Hello World";

// Bad
newMessage = 1;

keyof

オブジェクトの型からプロパティ名(キー)を型とするのが keyof になります。

type KEYS = {
  first: string;
  second: string;
};

let value: keyof KEYS;

// Good
value = "first";
value = "second";

// Bad
value = "third";

enum

enum(列挙型) は自動で連番をつけてくれる機能になります。
下記だとSOCCERに 0、BASEBALLに 1 が割り当てられます。
enum を用いることで可読性が高まり、メンテナンスしやすくなります。

enum SPORTS {
  SOCCER,
  BASEBALL,
}

interface STUDENT {
  name: string;
  club: SPORTS;
}

// clubに1が割り当てられる
const studentA: STUDENT = {
  name: "Ken",
  club: SPORTS.BASEBALL,
};

Generics

Generics を用いることで使用する度に型を宣言することができます。
同じようなコードを別の型で繰り返す場合などに役立ちます。
慣習的にTなどが使われることが多いです。

interface GEN<T> {
  msg: T;
}

// 使用する際にTの型を宣言する
const genA: GEN<string> = { msg: "Hello" };
const genB: GEN<number> = { msg: 2 };

// Bad
const genC: GEN<number> = { msg: "message" };

デフォルトの型を定義すると<string>などの宣言が任意になります。

interface GEN<T = string> {
  msg: T;
}

const genA: GEN = { msg: "Hello" };

またextendsを併せて用いることで使用できる型を制限することができます。

interface GEN<T extends string | number> {
  msg: T;
}

// Good
const genA: GEN<string> = { msg: "Hello" };

// Good
const genB: GEN<number> = { msg: 2 };

// Bad
const genC: GEN<boolean> = { msg: true };

関数で使う場合

function func<T>(value: T) {
  return value;
}

func<string>("Hello");

// <number>がなくてもよい
func(1);

// 型は複数でもよい
func<string | null>(null);

関数でextendsを使う場合

function func<T extends string>(value: T) {
  return value;
}

// Good
func<string>("Hello");

// Bad
func<number>(123);

interface と併せて使う場合

interface Props {
  name: string;
}

function func<T extends Props>(value: T) {
  return value;
}

// Good
func({ name: "Taro" });

// Bad
func({ name: 123 });

おわりに

いかがだったでしょうか。
今回は TypeScript の基礎について一部ご紹介しました。
TypeScript はフロントエンドの現場で使われていること増えてきており、
採用することでデータ型の不一致を防ぎバグの少ない安全な開発ができると思います。
少しでもこの記事がお役に立てば幸いです!
テックブログには他に様々な記事がありますのでよければご覧ください!

Facebook

関連記事 | Related Posts

We are hiring!

【フロントエンドエンジニア】新車サブスク開発G/東京・大阪

新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。​業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。

【フロントエンドエンジニア(コンテンツ開発)】新車サブスク開発G/東京・大阪

新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。​業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。