SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

基礎からはじめるReact Native入門

静的型チェックを行うTypeScriptで品質を担保しよう

基礎からはじめるReact Native入門 第12回

TypeScriptとは

 TypeScriptはMicrosoft社が開発したプログラミング言語です。

図1: TypeScriptの公式サイト
図1: TypeScriptの公式サイト

 JavaScriptの文法をベースに、型注釈をつけるための特別な文法で拡張されているのが、大きな特徴です。裏を返せば、型注釈に関する文法以外の大部分がJavaScriptの文法でできているので、JavaScriptが書ける人は少しだけ学習コストをかければTypeScriptを習得できることになります。

 拡張子は基本的に.tsですが、ReactなどでJSXを記述する場合だけ.tsxになります。また、tscというコマンドで静的型チェックやコンパイルを行います。

型注釈の基本

 型注釈の付与は、リスト2で紹介した通り、変数や引数、関数などに型注釈を明示して、tscコマンドによる型チェックの恩恵を受けられるようにする機能です。基本的な注釈の仕方は、図2の2つのパターンを覚えておけば良いでしょう。

図2:型注釈の基本形
図2:型注釈の基本形

 変数宣言に型注釈をすると、右辺と左辺の型に齟齬がないかをチェックできるようになります。関数定義に型注釈をすると、呼び出し側で引数に渡した値の型との齟齬がないかをチェックできるほか、戻り値の型を別の式でのチェックに利用できるようになります。また、TypeScriptには型推論という機能があり、右辺や戻り値から型が推測できるときには、型宣言が省略できる場合があります。リスト3でいくつかの実例を見てみましょう。

[リスト3]型チェックのパターン
// 問題ない
const numberValue: number = 1;
// 型に齟齬があるためエラー
const numberValue2: number = '1';
// 右辺がstring型なので、左辺の型注釈を省略してもstringValueはstring型として扱われる
const stringValue = 'abc';

// (1) 戻り値がstring型なので、戻り値の型注釈を省略しても戻り値の型はstring型として扱われる
function func(count: number) {
  return `現在のカウントは${count}です`;
}
// 左辺の型注釈と、右辺の戻り値型に齟齬がないかチェックされる
const message: string = func(numberValue);
// (2) 右辺の戻り値がstring型であることが分かっているので、左辺の型注釈は省略しても良い
const message2 = func(numberValue);
// 引数の型に齟齬があるためエラーとなる
const message3 = func(stringValue);

 (1)や(2)のパターンでは、引数以外の型注釈を省略できました。型を省略できるケースは多いので、明示的にチェックしたい場所以外は、可能な限り省略しておくと良いでしょう。

型の種類

 さて、ここまでの解説でstringnumberといった型を取り上げてきましたが、どんな型が使えるのかを確認しておきましょう。まず、表1にある通り、JavaScriptのtypeofで確認できる型と同じものは利用することができます。

表1:JavaScript由来の型
型名 意味
string 文字列型
number 数値型
boolean 真偽値型
undefined 未定義の値の型
functon 関数型
object オブジェクト型

 これらに加えて、柔軟な型定義を実現できるように、表2のTypeScript独自の型も用意されています。

表2:TypeScript独自の型(一部)
型名 意味
any 何でも型
{ a: number } オブジェクトリテラル型
(a: number) => number 関数型

 特によく使うものをピックアップしました。それぞれの例はリスト4の通りです。

[リスト4]TypeScript独自の型の例
// (1) anyはどんな値でも受け付ける
let anyValue: any = 1;
anyValue = 'abc'; // エラーにならない

// (2) オブジェクトリテラル型はオブジェクトの構造を定義する
const person: { name: string, age: number } = {
  name: '太郎',
  age: 24,
};

// (3) 関数の引数と戻り値の型を定義するための型表現
function func(callback: (id: number) => void) {
  callback(100);
}

 (1)のany型は、型を明確に定義できないことを明示する場合に使用する型です。正しい型を定義する労力がかけられない場合に利用します。(2)のオブジェクトリテラル型は、object型をより詳細に表現するためのもので、オブジェクトの階層構造をオブジェクトと似た記法で定義する、複合的な型です。リスト4の例では{ name: string, age: number }が全体で1つの型として扱われます。(3)の関数型はfunction型をより詳細に表現するためのもので、アロー関数に似た記法で定義します。voidは「戻り値がない」ことを明示するための特殊な型です。

型に名前をつける

 オブジェクトリテラルを使うことで、複雑な階層のオブジェクトでも、どんなプロパティ名にどんな型の値がひもづいているのかを、直感的に表現できます。しかし、いちいち{ name: string, age: number }の型を書くのは面倒ですね。

 TypeScriptには、型に名前をつけて、新しい型として定義するための文法があります。typeinterfaceの2つがありますが、できることにほとんど違いがないため、本記事ではtypeについて解説します。type記法は変数宣言と似た記法で、左辺に型の名前、右辺に元となる型を記述します(図3)。

図3:typeで型に名前をつける
図3:typeで型に名前をつける

 このPerson型を使うと、前述のリスト4の(2)はリスト5の通りに書き換えられます。

[リスト5]自作した型で変数宣言を行う
type Person = { name: string, age: number };

const person: Person = {
  name: '太郎',
  age: 24,
};

 こうして生み出した新しい型名は、通常のオブジェクトと同じようにimportexportすることができます。アプリケーション内で共通で扱いたいデータ型があれば、ファイルやフォルダで整理しておくと、複数人での開発がはかどることでしょう。

ライブラリの型情報

 さて、自分のプロジェクトで型を活用する方法については分かってきましたが、ここで気になるのは、よそから持ってきたライブラリの型はどうするのかというところです。幸い、TypeScriptにはJavaScript製のライブラリに型情報を添えて配布するための仕組みが整っています。型情報は.d.tsという拡張子で定義され、JavaScriptファイルと合わせて読み込むことで、自分のプロジェクトでTypeScriptのコードを扱うのと同じように、型の恩恵を受けることができます。

 ライブラリの型情報を利用する方法は、ライブラリがTypeScriptをサポートしているかどうかで変わってきます。ライブラリが公式にTypeScriptをサポートしている場合は、ライブラリに.d.tsファイルが同梱されるので、npm installが完了した段階でnode_modulesに型情報がインストールされます。この場合は、特に追加の作業をせずに、型情報を利用することができます。

 公式サポートがない場合でも、DefinitelyTypedと呼ばれるプロジェクトでサードパーティの型情報が提供されていれば、これを利用できます。@types/ライブラリ名の名前で配布されているパッケージをnpm installすると、型情報が利用できるようになります。

 型情報がまったく提供されていない場合は、.d.tsファイルを自作できますが、慣れるまでは型情報が用意されているライブラリを選んで使うと良いでしょう。

TypeScriptとBabelを併用する

 元々のtscコマンドは「TypeScriptコードを任意のバージョンのJavaScriptに変換するためのコマンド」として生み出されました。しかし、BabelがJavaScriptコンパイラとしての地位を確立していくにつれて、「型チェックはTypeScriptでやりたいけれど、JavaScriptへの変換はBabelでやりたい」といった要求も増えていき、住み分けが難しくなっていきました。

 この問題は、次の2つのアプローチによって解決されました。

  • tscコマンドに静的型チェックのみを行い、JavaScriptへの変換を行わないモードを設けた
  • TypeScriptコードからTypeScript固有の表現を排除するためのBabelプラグイン集として@babel/preset-typescriptを開発した

 前述の通り、TypeScriptはほとんどJavaScriptの文法でできているため、@babel/preset-typescriptによって型注釈やtypeによる型定義を削除する前処理によって、通常のBabelで処理できるJavaScriptコードが生成できます。これにより、Babelによるコンパイルを行っていた多くのプロジェクトで、TypeScriptの導入が進むことになったのです。

次のページ
React NativeとTypeScript

この記事は参考になりましたか?

基礎からはじめるReact Native入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川 幸哉(ナカガワ ユキヤ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/12432 2020/06/23 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー