そろそろ TypeScript をきちんと勉強するかー、ということで 公式ページ の Handbook を読み進めていった読書(?)メモ。
バージョンとしては 2.2 になるのかな? 随時更新中
公式ページの適当翻訳メモなので、間違いがあってもご了承ください。
- Basic Types (今ココ)
- Variable Declarations
- Interfaces
- Classes
- Functions
- Generics
- Enums
- Type Inference
- Type Compatibility
- Advanced Types
- Symbols
- Iterators and Generators
- Modules
- Namespaces
- Namespaces and Modules
- Module Resolution
- Declaration Merging
- JSX
- Decorators
- Mixins
- Triple-Slash Directives
- Type Checking JavaScript Files
Basic Types
Boolean
boolean 型あります。
let isDone: boolean = false;
var isDone = false;
Number
数値はすべて浮動小数点として扱います。
16 進数、10 進数に加えて、8 進数、2 進数もサポートしてます。
8 進数、2 進数サポートはすごいけど、使いドコロあるんだろうか…
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
var decimal = 6;
var hex = 0xf00d;
var binary = 10;
var octal = 484;
String
文字列はダブルクォート("
)またはシングルクォート('
)で囲みます。
let color: string = "blue";
color = 'red';
var color = "blue";
color = 'red';
バッククォート(`
)で囲んだ文字列には ${ expr }
で変数・式を埋め込めます。
${...}
の中は式として評価されるので、${
}
前後の空白はあってもなくても問題ない。
let fullName: string = `Bob Bobbington`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ fullName }.
I'll be ${ age + 1 } years old next month.`
var fullName = "Bob Bobbington";
var age = 37;
var sentence = "Hello, my name is " + fullName + ".\n\nI'll be " + (age + 1) + " years old next month.";
これは便利だ。
しかも文字列中の改行は自動的に \n に置き換えてくれてる。
Array
配列は以下の 2 通りの宣言方法をサポートしてます。
配列を組み込み型と考えるか、オブジェクトと考えるかで好みが分かれそう。
もっとも、大事なことは表記を統一することだね。
let list1: number[] = [1, 2, 3];
let list2: Array<number> = [1, 2, 3];
var list1 = [1, 2, 3];
var list2 = [1, 2, 3];
Tuple
指定した型の組のことを Tuple と呼びます。
// 宣言
let x: [string, number];
// 初期化
x = ["hello", 10]; // OK
// 初期化 (間違い)
x = [10, "hello"]; // エラー
// 宣言
var x;
// 初期化
x = ["hello", 10]; // OK
// 初期化 (間違い)
x = [10, "hello"]; // エラー
各要素にアクセスするときはインデックスでアクセスします。
console.log(x[0].substr(1)); // OK
console.log(x[1].substr(1)); // エラー。 2 番目の要素は 'number' なので substr は使えない。
範囲外の要素にアクセスした場合、自動的に共用型として扱います。
x[3] = "world"; // OK。 'string' は 'string | number' 型に代入可能。
console.log(x[5].toString()); // OK。 'string' と 'number' 両方にあるメソッドは呼び出し可。
x[6] = true; // エラー。 'boolean' は 'string | number' 型には代入できない。
Enum
TypeScript は Enum をサポートしてます。
コンパイル後のコードがすごい…
enum Color {Red, Green, Blue};
let c: Color = Color.Green;
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));
;
var c = Color.Green;
Enum はデフォルトでは 0 からナンバリングされますが、好きな数字からナンバリングすることも可能ですし、
enum Color {Red = 1, Green, Blue};
let c: Color = Color.Green;
var Color;
(function (Color) {
Color[Color["Red"] = 1] = "Red";
Color[Color["Green"] = 2] = "Green";
Color[Color["Blue"] = 3] = "Blue";
})(Color || (Color = {}));
;
var c = Color.Green;
すべて自分でナンバリングすることも可能です。
enum Color {Red = 1, Green = 2, Blue = 4};
let c: Color = Color.Green;
var Color;
(function (Color) {
Color[Color["Red"] = 1] = "Red";
Color[Color["Green"] = 2] = "Green";
Color[Color["Blue"] = 4] = "Blue";
})(Color || (Color = {}));
;
var c = Color.Green;
インデックスから Enum の要素を取得することも可能です。
enum Color {Red = 1, Green, Blue};
let colorName: string = Color[2];
console.log(colorName); // 上の Color[2] に対応する値である 'Green' を表示する
var Color;
(function (Color) {
Color[Color["Red"] = 1] = "Red";
Color[Color["Green"] = 2] = "Green";
Color[Color["Blue"] = 3] = "Blue";
})(Color || (Color = {}));
;
var colorName = Color[2];
console.log(colorName); // 上の Color[2] に対応する値である 'Green' を表示する
Any
Any 型を使えば型チェックをバイパスすることができます。
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // 今度は boolean
var notSure = 4;
notSure = "maybe a string instead";
notSure = false; // 今度は boolean
Object 型でも似たようなことができますが、任意の型を代入できるだけで、その型のメソッドを呼ぶことはできません。
Object 型なんだから、Object 型で宣言されているメソッドしか呼べないのは当たり前だね。
let notSure: any = 4;
notSure.ifItExists(); // OK。 実行時には ifItExists メソッドが存在するはず
notSure.toFixed(); // OK。 toFixed メソッドは存在する (けど、コンパイル時チェックはしない)
let prettySure: Object = 4;
prettySure.toFixed(); // エラー。 toFixed メソッドは Object 型には存在しない。
Any 型は他の型の一部としても使えます。
let list: any[] = [1, true, "free"]; // 任意の型を含められる
list[1] = 100;
var list = [1, true, "free"]; // 任意の型を含められる
list[1] = 100;
Void
Void は型がないことを表すもので、値を返さない関数の戻り値でよく使います。
function warnUser(): void {
console.log("This is my warning message");
}
function warnUser() {
console.log("This is my warning message");
}
Void 型には undefined
か null
しか代入できません。
let unusable: void = undefined;
Null と Undefined
Null 型と Undefined 型にはそれぞれの値しか代入できません。
let u: undefined = undefined;
let n: null = null;
デフォルトでは undefined
、null
は任意の型に代入することができますが、--strictNullChecks
フラグを指定した場合、 Void 型かそれぞれの型にしか代入できなくなります。
その状態で undefined
、null
の代入を許可したい場合は共用型 (例: 'string | null | undefined'
) を使います。
公式ページでは
--strictNullChecks
の使用を推奨しているので、なるべく使った方が良さそう。
Never
Never 型は値を返さないことを表します。
これまた使いドコロが難しそうな…
// 例外をスローするのでメソッドの最後まで絶対に到達しない
function error(message: string): never {
throw new Error(message);
}
// Never 型を return するなら、そのメソッドの戻り値も Never 型になる
function fail() : never {
return error("Something failed");
}
// 無限ループするのでメソッドの最後まで絶対に到達しない
function infiniteLoop(): never {
while (true) {
}
}
Object
object
は非プリミティブ型、つまり number
、string
、boolean
、symbol
、null
、undefined
以外の型を表す型です。
object
型を使用すると Object.create
のような API をより分かりやすく記述することができます。
declarefunctioncreate(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // エラー
create("string"); // エラー
create(false); // エラー
create(undefined); // エラー
Type assertions
キャストは以下の 2 通りの表記をサポートしてます。
ただし、JSX を使用する場合、as
形式の表記のみ使用可能です。
let someValue: any = "this is a string";
let strLength1: number = (<string>someValue).length;
let strLength2: number = (someValue as string).length;
var someValue = "this is a string";
var strLength1 = someValue.length;
var strLength2 = someValue.length;