※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。

<前のページ
Ubuntu20.04LTSでTypeScriptの環境を構築
次のページ>
TypeScriptの型について - 基本

TypeScriptの型システムの基礎

トランスパイル TypeScript 型付き言語 静的型付け

投稿日:2020年11月11日

このエントリーをはてなブックマークに追加
TypeScriptは静的型付け言語です。Javascriptの動的型付けとは挙動が異なっていて、その点に注意しないと思わぬバグを生んでしまいます。この記事ではTypeScriptにおける型システムについて解説しています。

はじめに

この記事について

この記事ではTypeScriptの型システムの基礎について解説しています。


明示的型指定と暗黙的型指定

TypeScriptの型指定には明示的な構文で指定する方法と、型を自動的に推論させる方法の2つの方法があります。

明示的な型指定(implicit type declaration)

型を明示的に指定する場合、アノテーションという値: 型

の形式で記述を使用します。

explicit.ts
let age: number = 26                          // 数値
let username: string = "marsquai"             // 文字列
let is_superuser: boolean = true              // bool
let areaIdArray: number[] = [1,2,3,4,5]                // 配列
let userIdArray: Array<number> = [1,2,3,4,5]           // 配列
let userInfo: [string, number, number] = ["marsquai", 26, 171]   // タプル

指定した型と異なる値を入れようとした場合、トランスパイル時にエラーが投げられます。

explicit.ts
let age: number = "26"                          // 数値
let username: string = 111111111111             // 文字列
let is_superuser: boolean = 0              // bool
let areaIdArray: number[] = ["aaa","bbb"]                // 配列
let userIdArray: Array<number> = 100           // 配列
let userInfo: [string, number, number] = [171, "200"]   // タプル
ターミナル
$ tsc explicit.ts
explicit.ts:1:5 - error TS2322: Type 'string' is not assignable to type 'number'.

1 let age: number = "26"                          // 数値
      ~~~

explicit.ts:2:5 - error TS2322: Type 'number' is not assignable to type 'string'.

2 let username: string = 111111111111             // 文字列
[...]

Found 8 errors.

暗黙的な型指定(explicit type declaration)

型を指定しなかった場合、型は自動的に推論されます。

implicit.ts
let age: number = 26                          // 数値
let username: string = "marsquai"             // 文字列
let is_superuser: boolean = true              // bool
let areaIdArray: number[] = [1,2,3,4,5]                // 配列
let userIdArray: Array<number> = [1,2,3,4,5]           // 配列
let userInfo: [string, number, number] = ["marsquai", 26, 171]   // タプル

型を指定しなかった場合にも、内部的には型は存在しています。

変数宣言時に値を代入している場合、その値と違う型の値を入れようとするとエラーが投げられます。

implicit.ts
let firstName = "marsquai"
firstName = 10
ターミナル
$ tsc implicit.ts
implicit.ts:2:1 - error TS2322: Type 'number' is not assignable to type 'string'.

2 firstName = 10
  ~~~~~~~~~


Found 1 error.

また、内部的に型が存在しているため、VSCodeなどのエディタのインテリセンスで、は、その型のメソッドなどを正しく表示してくれます。

(これは素晴らしい!!)

▲Stringのメソッドをインテリセンスが表示

実行環境ごとの型

Javascriptの実行環境によってはその実行環境側で型を定義していたりします。

しかし、デフォルトの状態のTypeScriptはそれぞれの実行環境でどのような型が使えるのかを知る術がありません。

例えば、

nodejsにはBuffer型というものがあります。

TypeScriptをインストールしただけの環境で以下のようなコードを書いた場合、

sample.ts
let buffer: Buffer;

トランスパイルでエラーがなげられてしまいます。

ターミナル
$ tsc sample.ts
sample.ts:1:13 - error TS2580: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i @types/node`.

1 let buffer: Buffer;
              ~~~~~~


Found 1 error.

この問題は型の宣言をインストールすることで解決できます。

開発している環境にnpmがインストールされている場合、ほぼすべての型はそれでインストールすることができます。型のパッケージの名前は@type/~~~のような形になっています。

今回のnodejsの場合パッケージ名は@types/nodeです(エラーメッセージにも書いてありますね!!)。

プロジェクトで使用するパッケージは、デプロイや複数人での共同作業を考えると、そのプロジェクトのディレクトリ内だけで依存関係を解決できることがのぞましいです。

npmのインストールのオプションに--save-devをつけることで作業ディレクトリのnode_modulesというディレクトリに依存関係を入れることができます。

ターミナル
$ npm init # プロジェクトの初期化
$ npm install --save-dev typescript @types/node

(一応TypeScriptも入れておきました!)

以下のようなBufferの定義がインストールされているはずです。

node_modules/@types/node/globals.ts
[...]
declare class Buffer extends Uint8Array {
    /**
     * Allocates a new buffer containing the given {str}.
     *
     * @param str String to store in buffer.
     * @param encoding encoding to use, optional.  Default is 'utf8'
     * @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead.
     */
    constructor(str: string, encoding?: BufferEncoding);
    /**
[...]

再度トランスパイルしてみましょう!

ターミナル
$ tsc sample.ts

問題なくコンパイルできました!


さいごに

参考書籍

このエントリーをはてなブックマークに追加

<前のページ
Ubuntu20.04LTSでTypeScriptの環境を構築
次のページ>
TypeScriptの型について - 基本

関連記事

記事へのコメント