サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

TypeScript: 基本型


TypeScriptで用いられる基本的なデータ型についてご説明します。JavaScriptに備わるデータ型だけでなく、TypeScriptがECMAScript 2015の仕様も採り入れて、加えた型や機能もあります。

01 ブーリアン(論理)型

true(真)かfalse(偽)の二値どちらかをとるのがboolean(論理)型です。JavaScriptにも備わっています。値をtypeof演算子で調べると、"boolean"が返ります。


let isDone: boolean = false;
console.log(typeof isDone);  // boolean

02 数値型

JavaScriptと同じく、TypeScriptもすべての数値を浮動小数値として扱います。データ型はnumberです。typeof演算子は"number"を返します。JavaScriptが扱う10進数と16進数に加えて、TypeScriptではECMAScript 2015 (ES6)で採り入れられた2進数および8進数も使えます。数値の頭に2進数は0b、8進数は0oを添えます(MDN「字句文法」の「Numeric リテラル」参照)。


let decimal: number = 27;
let hex: number = 0x1b;
let binary: number = 0b11011;
let octal: number = 0o33;
console.log(decimal, hex, binary, octal);  // 27 27 27 27

03 文字列型

テキストなどの文字列データは、stringで型づけします。typeof演算子の戻り値は"string"です。JavaScriptと同じく、値はダブルクォート(")またはシングルクォート(')の引用符でくくります。文字列にクォーテーション記号そのものを含めたいときは、もう一方の引用符を用いればよいでしょう。


let pen: string = "I have a pen.";
let apple: string = 'I have an "apple".';

TypeScriptには、ECMAScript 2015のテンプレート文字列も採り入れられました。クォーテーションの替わりにバックティック(`)でくくることで、値の中で改行や文字列内挿機能(${})が使えます。


let today: Date = new Date();
let days: string[] = ['日', '月', '火', '水', '木', '金', '土'];
let dayOfWeek: string = `本日の曜日:
${days[today.getDay()]}曜日`
console.log(dayOfWeek);  /* 今日が金曜日であれば
本日の曜日:
金曜日*/

もちろん、つぎのように書くこともできます。コンパイルされたコードは、ほぼこのかたちです。


let dayOfWeek = '本日の曜日:\n' + days[today.getDay()] + '曜日';

04 配列

配列はArrayクラスのインスタンスです。typeof演算子からは"object"が返されます。配列のデータ型は、要素の型を添えて定めます。構文はふたつあり、ひとつはつぎのように要素の型に角かっこ[]を加えます。


let list: number[] = [1, 2, 3];

もうひとつは、Arrayクラスをジェネリックで型づけする書き方です。山かっこ<>の中に要素の型を与えます。


let list: Array<number> = [1, 2, 3];

JavaScriptと同じように要素の型を問わない場合には、anyで型づけすればよいでしょう。


let list: any[] = [1, 'b', new Date()];

要素のデータが任意ではなく、複数の型を与えたいなら、Union型が使えます。[]の構文の場合は、要素の型は丸かっこ()でくくってください。


let list: (number | string)[] = [1, 'b', 3];

ジェネリック型の書き方では、山かっこ<>の要素の型づけにUnion型を用います。


let list: Array<number | string> = [1, 'b', 3];

05 タプル型

タプル型は、配列に要素ごとの型を定めます。配列に、決められた型で要素が納められていないとエラーになります。要素の値を書き替えるときも、決められた型のデータでなければなりません。


let list: [number, string];
list = [1, 'b'];
// list = ['1', 'b'];  // 要素の型が違うのでエラー
// list = [1];  // 要素が足りないのでエラー

新たな要素を加えることはできます。ただし、その型はタプルに与えた型のいずれかでなければなりません。


list = [1, 'b', 3];
// list = [1, 'b', new Date()];  // タプルにDate型が与えられていないのでエラー

要素を取り出してプロパティやメソッドを参照するときは、その要素の型ごとに評価されます。したがって、ひとつの要素で参照できたプロパティやメソッドも、他の型の要素で使おうとすればエラーになる場合があります。


console.log(list[0].toString(2));  // インデックスが1だとエラー
console.log(list[1].length);  // インデックスが0だとエラー

06 列挙型

列挙型enumは、数値に識別子を与えます。デフォルトでは、数値は0から始まる連番整数です。数値が名前で扱え、enumで型づけすれば使われる数値もはっきりします[*1]


enum Index {zero, one, two};
console.log(Index);
// { '0': 'zero', '1': 'one', '2': 'two', zero: 0, one: 1, two: 2 }
let id: Index = Index.one;

識別子に与える数値は、代入のかたちで変えられます。そのあとの値を与えられていない識別子は、その値からの連番整数になります。


enum Index {zero, one = 11, two};
console.log(Index);
// { '0': 'zero', '11': 'one', '12': 'two', zero: 0, one: 11, two: 12 }

enumは識別子で数値を定めるだけではありません。数値から識別子を調べることもできます。


enum Color {red = 0xFF0000, green = 0xFF00, blue = 0xFF};
let color: Color = Color.blue;
let colorName: string = Color[color];
console.log(color, colorName);  // 255 'blue'

[*1] enumで型づけしても、与える数値そのものは縛れません。

enum Index {zero, one, two};
let id: Index = 100;  // エラーにならない
console.log(id);  // 100

07 any型

データ型を予め決められないときは、any型が使えます。たとえば、ユーザーやサードパーティのライブラリで、値が動的に与えられる場合などです。前述の要素の型を問わない配列に用いる場合もありました。anyで型づけされたデータは、コンパイルするとき型にもとづくチェックが省かれます。


let list: any[] = [1, 'b', new Date()];

Objectクラスで型づけした変数には、任意のプロパティを加えたオブジェクトが代入できます。けれど、その値を調べようとすると、エラーになってしまいます。Objectクラスに定義済みでないプロパティは参照できないのです。


let object: Object = {
	prop: 1
};
// console.log(object.prop);  // Objectクラスに定義されていないプロパティなのでエラー

変数をanyで型づけすれば、どのようなプロパティやメソッドを加えても参照できます。ただし、プロパティのデータ型はもちろん、その存在さえ確かめられなくなることにご注意ください。


let object: any = {
	prop: 1
};
console.log(object.prop);  // 1
console.log(object.prop.length);  // undefined
console.log(object.nothing);  // undefined

オブジェクトに加えるプロパティとデータ型が決まっているときは、オブジェクト型リテラルあるいはインタフェースを使うのがよいでしょう。


let object: {prop: number} = {
	prop: 1,
};
console.log(object.prop);  // 1
console.log(object.prop.toString(2));  // 1
// console.log(object.prop.length);  // データ型に備わっていないのでエラー
// console.log(object.nothing);  // 型づけに与えられていないのでエラー

08 void型

void型は値がないことを示します。おもに用いられるのは、関数の戻り値の型づけでしょう。


function warn(): void {
    alert('warning');
}

変数に使えないわけではありません。ただ、値として納められるのはundefinednullだけです。実際に用いられることは、ほとんどないでしょう。


let unusable: void = undefined;

09 undefined型とnull型

undefinednullには、それぞれundefinedおよびnullという型が定められています。けれど、これらの型づけを単独で用いることはなさそうです。


let _undefined: undefined = undefined;
let _null: null = null;

TypeScript 2.0から--strictNullChecksのモードが備わりました。このモードではnullundefinedは、それぞれの型とvoidの型づけでしか値が受け取れません。データがより厳しく扱えるので、TypeScriptは--strictNullChecksモードを推奨しています。けれど、値がなくても一旦受け取り、その判定をしたうえで、処理は進めたい場合もあるでしょう。そのようなときは、undefinednullをUnion型で用います。


let text: string | undefined | null;

10 never型

決して起こらないのがnever型です。関数が正しく終わらなければ、値は返せません。必ずエラーになる関数の戻り値は、never型になります。voidでも型づけは可能です。正しく終わらないことを明らかにするための型といえます。


function error(message: string): never {
    throw new Error(message);
}
function fail(): never {
    return error("failed");
}

function infiniteLoop(): never {
    while (true) {}
}

変数をneverで型づけることもできます。このとき、代入できるのはnever型の値だけです。


let neverDone: never = (() => {
	throw new Error('failed')
})();

11 型変換

ある型のデータを別の型で指定し、評価し直します。型アサーション(type assertion)あるいはキャストと呼ばれる機能です。ただし、TypeScriptがとくにデータをチェックしたり、構築し直すことはありません。実行時の負荷にはならないということです。

ふたつの構文があり、ひとつは山かっこ<>を用います。


let someValue: any = 'this is a string';
let length: number = (<string>someValue).length;

もうひとつは、as構文です。どちらの構文でも、処理の中身は変わりません。ただし、JSXを使うときは、asのみ許されます。


let someValue: any = 'this is a string';
let length: number = (someValue as string).length;

12 letキーワードについて

TypeScriptでは変数をJavaScriptと同じvarで宣言することもできます。けれど、TypeScriptでは、できるだけlet宣言を使うことが推奨されています。キーワードvarletの違いについては、「TypeScript入門 07: ブロックスコープに変数を宣言する ー let」をお読みください。

13 型づけを使ったコード例

Qiita「TypeScriptの型づけを使う ー Union型、列挙型、型の別名など」は、ここまで解説したいくつかの型を用いたコード例です。ビット演算の応用も交えてご紹介しています。


作成者: 野中文雄
更新日: 2017年2月13日 13「型づけを使ったコード例」を追加。
作成日: 2017年1月27日


Copyright © 2001-2017 Fumio Nonaka.  All rights reserved.