K.Takahashiをフォローする

TypeScript入門!メリットと使い方をやさしく解説

フロントエンド

弊社でも最近TypeScriptを使用したプロジェクトにアサインする機会が増えています。

しかし、そもそもTypeScriptとはどのようなもので、どのような利点があるのかを正確に理解している人は私含めて少ないように感じます。

今回は私の学習も兼ねてTypeScriptの概要とメリット、使い方を紹介していきます。

TypeScriptとは?

TypeScriptはJavaScriptのスーパーセット(上位互換の言語)で、主に静的型付けの機能が追加されています。

TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.
(引用:https://www.typescriptlang.org/

JavaScriptで大規模アプリケーションを開発する上での欠点を補うためにマイクロソフトなどによりつくられ、2012年10 月に公開されました。

どれくらい人気なのか?

TypeScriptは2022年の第一四半期にGithubでの言語使用率第4位にランクインしています。
(引用:GitHut 2.0

また、Googleも2017年の4月から社内の標準言語として、TypeScriptを採用しています。
(引用:Keynote Day 3 – BRAD GREEN and ROB WORMALD

これらのデータからTypeScriptが多くのプロジェクトで採用されており、ReactやVue.jsとセットで使われることも多いので、特にフロントエンドエンジニアにとってはほぼ必須のスキルといっても過言ではありません。

そもそも「静的型付け」とは何か?

プログラミング言語には「動的型付け言語」「静的型付け言語」の2種類が存在します。

動的型付け言語

変数や関数の引数・返り値にデータ型の宣言がいらないプログラミング言語です。
【代表的な言語】Python、Ruby、JavaScript、PHP、etc.

▼JavaScriptの例▼

const language = 'JavaScript';

const getLanguage = (language) => {
    return `${language} is used.`;
}

プログラムの記述量が少なく、データ型を意識する必要がないので学習コストが低いといった利点があります。

▼TypeScriptの例▼

type LanguageType = 'C/C++' | 'C#' | 'Java' | 'Go' | 'TypeScript';

const language: LanguageType = 'TypeScript';

const getLanguage = (language: LanguageType): string => {
    return `${language} is used.`;
}

事前にコンパイルを行うので、プログラムの実行前に型の整合性をチェックし、エラーを検出することができる利点があります。

TypeScriptのメリット/デメリット

メリット

保守性が向上する

例えば、チームで開発したり、途中から他のプロジェクトにアサインしたりした際に、このような経験はありませんか?

  • 関数の引数に誤った値を入れてしまいバグを起こしてしまった
  • オブジェクトのプロパティを誤って削除・改名・参照してしまいバグを起こしてしまった

TypeScriptを使用することで、関数の引数に何をいれるべきか、オブジェクトはどのようなプロパティで構成されているのかが明確になり、不注意で起こるバグを減らすことができます。

コードの誤りに気付きやすくなる

型のエラーが存在する場合、コンパイル時に以下のようなエラーが表示されます。

またVSCodeなどを使用すると、エディター上でエラーを検出することができます。

パフォーマンスが向上する

例えば、2つの数字(number1、number2)を掛け算する関数をつくる場合に、JavaScriptですと引数の型が確定していないので例外処理を記述する必要があります。

const multiply = (number1, number2) => {
  # number1またはnumber2が数値でない場合は0を返す
  if (typeof number1 !== 'number' || typeof number2 !== 'number') {
    return 0;
  }
  return number1 * number2;
};

一方でTypeScriptを使用しますと、引数および返り値の型を予め指定できるので、余計な例外処理をせずに済みます。

const multiply = (number1: number, number2: number): number => (
  # number1とnumber2が数値であることは確定しているので例外処理は不要
  number1 * number2
);

デメリット

学習コストがかかる

TypeScriptの使い方を開発メンバーに学んでもらう必要があります。

JavaScriptの上位互換の言語なので、JavaScriptを問題なく使えるメンバーが多ければ気にする必要はありませんが、新人が多いプロジェクトでは余計な学習コストをなくすためにTypeScriptを使用しないという選択肢もあります。

TypeScript未対応のパッケージがある

TypeScriptに未対応のパッケージを使うときに苦労します。

ただし、メジャーなパッケージのほとんどは「@types/~」のような型定義のパッケージが用意されているので、特に気にする必要はありません。

コードが長くなる

型を宣言する分のコードが増えてしまいます。

ただし、型を別ファイルに定義して「import type」したり、型を再利用したりすることでコード量は抑えることができます。

TypeScriptの型定義

それでは実際にTypeScriptの使い方を見ていきます。

TypeScriptでは以下のような方法で型定義を行います。

一般的な型

論理型

const isOpen: boolean = true;

数値型

const count: number = 100;

文字列型

const count: string = 'typescript is useful.';

オブジェクト型

type ObjectType = {
    isOpen: boolean,
    count: number,
};

const testObject: ObjectType = {
    isOpen: true,
    count: 100,
};

配列型

type StringArrayType = string[];

const stringArray: StringArrayType = ['a', 'b', 'c'];

type NumberArrayType = number[];

const numberArray: NumberArrayType = [1, 20, 400];

ユニオン型

「|」を使って複数の型を列挙します。

type ColorType = 'Red' | 'Green' | 'Blue';

const color: ColorType = 'Red';

null/undefined型

const nullValue: null = null;

const undefinedValue: undefined = undefined;

type IncludeUndefinedType = {
    isOpen?: boolean, # boolean | undefined と同義
    count?: number, # number | undefined と同義
};

型アサーション

「as」で型を上書きします。

const value: string | number = 'Value is string,'; 

const valueLength: number = (value as string).length; # .lengthはnumberに使用できない

型の再利用

typeof 型演算子

const nameOfTaro = 'taro';
const oldOfTaro = 30;

type PersonalDataType = {
    name: typeof nameOfTaro, # string
    old: typeof oldOfTaro, # number
};

keyof 型演算子

type PersonalDataType = {
    name: string,
    old: number,
};

type Keys = keyof PersonalDataType;  # 'name' | 'old' と同義

ジェネリクス

型を引数にすることによって、typeを柔軟に定義することができます。

# TとUが引数になる
type PersonalDataType<T, U> = {
    name: T,
    old: U,
};

const data: PersonalDataType<string, number> = {
    name: 'Taro',
    old: 20,
};

おわりに

私も最初TypeScriptに触れたときは新しく覚えることが増えそうで億劫でした。

ですが実際に使ってみると意外に覚えることは少なく、JavaScriptの開発と比べて、余計な例外処理を書かずに済んだり、エラー箇所がすぐに分かったりするなど便利な点が多いと感じています。

今後もTypeScriptを使った開発は増えると思いますので、ぜひチャレンジしてみてください。