TypeScript超入門(2)：構文を理解する


[TypeScript超入門：とりあえず動く環境を作る](http://qiita.com/ringtail003/items/40c7e74b72ce5a371c46)の続きです。とりあえず動く環境は作ったものの、読めない、書けない....。まずは基本の構文を理解しようと本やサイトを見てまとめた記事です。

# この記事を書いた環境

`tsc v1.6.2`でコンパイル・検証しています

# 参考にしたサイト

> **[TypeScript早わかりチートシート【1.5.3対応】](http://www.buildinsider.net/language/quicktypescript/01)**
相当わかりやすいのでこの記事よりこちらを参考にしたほうがいいと思います。

#

> **[TypeScript Handsbook](http://www.typescriptlang.org/Handbook)**
公式マニュアル。
全部読めば理解できるんだろうけど、英語なのでちょっとツライです。

#

> **[ES6 exploringjs](http://exploringjs.com/es6/)**
TypeScriptはES6構文を積極的に取り入れています。
サンプルが多いので参考になります。

## 型の種類

### Boolean

```typescript
var x: boolean = false;
```

### Number

```typescript
script
var x: number = 1;
```

### String

```typescript
var x: string = 'hello';
```

### Any

型なしを示す。ノーチェックでコンパイルを通過するためできる限り使わない。

```typescript
var x: any;
```

```typescript
// 型を省略すると勝手にanyになる
var x;
```

```typescript
// 宣言と代入を同時に行うと型推論が動いてしまう
var x:any = 123; // number

// anyにしたい時は2行に分ける
var y:any;
y = 123; // 数値を持ったany
```

### Array

```typescript
var x: number[] = [1,2,3];
var y: string[] = ['a','b'];
var x: any[] = [1,'hello',true];
```

### Enum

```typescript
enum Color {Blue,Red};
var x: Color = Color.Red;
```

```typescript
// Enumの値で比較できる
console.log(x === Color.Red); // true

// 0からの連番で扱われる
console.log(x === 1); // true
```

```typescript
// キーになる数値を振る
enum Color {Blue=100,Red=200};
console.log(Color.Red); // 200
```

### Void

値を返さない関数の戻り値として使用する

```typescript
function f(): void{
	alert('message');
}
```

## 関数の書き方

```typescript
// 引数・戻り値に型を定義する(省略しても可)
function f(x: number): string {
	return x.toLocaleString() + '円';
}
console.log(f(1000)); // "1,000円"
```

```typescript
// 省略可能な引数は?を使う
function f(x: number, y?: string = '円'): string {
	return x.toLocaleString() + y;
}
console.log(f(1000)); // "1,000円"
console.log(f(1000, 'ペソ')); // "1,000ペソ"
```

### アロー関数式

```typescript
var add = (x: number): number => x + 1;
```

```typescript
// {}を使ってもOK
var add = (x: number): number => {
	return x + 1;
}
```

## クラス

### 書き方

```typescript
class A extends [super] implements [interface] {}

var x: A;
x = new A();
```

### アクセシビリティ

private/publicの2択

```typescript
class A {
	private x: number;
	public y: number;
}
```

```typescript
// デフォルトはpublic
class A {
	x: number;
}
```


### コンストラクタ

```typescript
class Person {
	constructor(public id: number) {
		// this.number=id; は自動的に行われるので省略
	}
}
```

### set/getアクセサ

```typescript
class Person {
	private firstName;
	private lastName;
         
	set fullName(name: string) {
		var names = name.split(' ');
		this.firstName = names[1];
		this.lastName = names[0];
	}                
	get fullName(): string { 
		return this.lastName + this.firstName + 'さん';
	}            
}              
                 
var p: Person;
p = new Person();
p.fullName = '小田 花子';      
console.log(p.fullName); // "小田花子さん"
```

> **注意**
es5の機能を使うため `$ tsc --target es5 [file]` とする必要がある

### 継承

**super** キーワードで親クラスを呼び出し

```typescript
class A {
	f(){}
}

class B extends A {
	constructor(){
		super();
	}
	
	f(){
		// 親クラスに存在するメソッドを呼べる(privateも可)
		super.f();
	}
}
```

## インターフェース

```typescript
interface A { 
	id: number;
	f(n: number): number;
}    

class B implements A {
	public id = 1;
	public f(n: number) {
		return n * 1;
	}
}  
```

### 複数インターフェース

```typescript
interface A {}
interface B {}

class X implements A,B {}
```

### インターフェースを継承したインターフェース

```typescript
interface A {}
interface B extends A {}

class C implements B {}
```

## オーバーロード

```typescript
class A{
	f(x:string): string;
	f(x:number): number {
		if (typeof x === 'string') {
			return x + ' abc';
		} else {
			return x + 1;
		}
	}
}

var x:A;
x = new A();
console.log(x.f('a')); // "a abc"
console.log(x.f(1)); // 2
```

## ジェネリック

実行時まで型が確定しない場合に仮の型を宣言できる。
型名にはT,U,V,T1,T2,T3...を使うのが一般的。

```typescript
function f<T>(x: T) {
	console.log(x);
}

func<string>('abc'); // "abc"
func<number>(123); // 123
func(123); // 省略も可
```

### 継承の制約として使用

```typescript
function f<T extends A>(p:T) {
	console.log(p.value);
}
```

### クラスの先頭で使用すると全体で使用できる

```typescript
class A<T> {
	private field: T;
	public f(x: T) {}
}
```

### インターフェースで使用する例

```typescript
interface A<T>{
	f(x: T);
}
```

```typescript
// 例1)クラスで型を指定
class C implements A<number> {
	f(x: number){}
}

var y: C;
y = new C();
y.f(123);
```

```typescript
// 例2)クラスは仮の型Tのまま
class B implements A<T> {
	f(x: T){}
}

// インスタンス作成時に型を指定
var x: B<string>;
x = new B();
x.f('abc');
```

## static

```typescript
class A {
	static id: number = 1;
	static f(): number { return 100; }
}
```

```typescript
// インスタンスから呼び出せない
var x: A;
x = new A();
console.log(x.id); // undefined
console.log(x.f()); // Error: not a function
```

```typescript
// 静的な参照のみ
console.log(A.id); // 1
console.log(A.f()); // 100
```

## モジュール

### 内部モジュール

```typescript
module A {
	export function a(){
		console.log('a');
	}
}

module B {
	export function b(){
		A.a();
		console.log('b');
	}
}

B.b();
// a
// b
```

```typescript
// ネストも可
module A {
	module B {}
}
```

```typescript
// 分割も可(別ファイルでもOK)
module A {
	function a1(){}
}

module A {
	function a2(){}
}
```


## タプル

複数要素のセットを表現する

```typescript
var x: [number, string] = [1, 'hello'];
x[0].toFixed();
x[1].charAt(0);
```

## 共有型

複数の型を持つことができる

```typescript
// 関数の戻り値で使用
function f(x: number): number | string {
	if (x >= 0) {
		return 1;
	} else {
		return 'error';
	}   
}
```

```typescript
// 変数に使用
var x: (number | string)[] = [];
```

## typeguard

型により処理を分岐する

```typescript
// プリミティブ
var x: (number | string);
...
if (typeof x === 'string') {...}
```

```typescript
// クラス
var x: (ClassA | ClassB);
...
if (x instanceof ClassA) {...}
```

## 型のエイリアス

```typescript
type NumberOrString = number | string;
```

```typescript
// 変数で使用
var x: NumberOrString;

x = 1;
x = 'abc';
```

```typescript
// 関数で使用
function f(x: number): NumberOrString {
	if (x >= 0) {
		return 1;
	} else {
		return 'error';
	}
}
```

* エイリアスを使用すると思われるのは、タプルまたは共有型
* 他は可能な限りinterfaceを定義したほうが良い

# TypeScriptで使用可能なES6構文

## let

スコープ内だけ生存する変数を宣言

```typescript
let x = 1;
{
	let x = 2;
}
console.log(x); // 1
```

```typescript
// 関数でも同じ
let x = 1;
function f(){
	let x = 2;
}
console.log(x); // 1
```

## const

定数

```typescript
const x = 123;
x = 456; // コンパイルエラー
```

### template literals

```typescript
var text = `
複数行の
テキストが
書ける
`;
```

```typescript
var html = `
<p>HTMLに</p>
<p>便利</p>
`;
```

`${}`を使うとリテラル内に式を埋め込むことができる

```typescript
var x: number = 1;
var text = `
答えは${x + 100}
`;
console.log(text); // "答えは101"
```

`${}`のリテラルを関数に渡すと変数と分割できる

```typescript
// HTMLのエスケープ処理などに使用できる
function tag(literal, ...values: any[]) {
	console.log(literal); // ["朝食は","","","","です"]
	console.log(values); // ["カレー","ラーメン","うどん"]
}
tag `朝食は${'カレー'}${'ラーメン'}${'うどん'}です`;
```

## shorthand properties

> これはtsc1.6.2では使用できなかった
いつか使えると思うのでメモとして残す

```typescript
var x = {id,name};
console.log(x);
```

## destructring

オブジェクトや配列を構造化(脱構造化)する

```typescript
var x = {id:1,name:'abc'};
var {id,name} = x;

console.log(id); // 1
console.log(name); "abc"
```

```typescript
var x:number[] = [100,200];
var [y1, y2] = x;

console.log(y1); // 100
console.log(y2); // 200
```

```typescript
// 引数に別名を付けることができる
function f({x: id, y: name}: {x: number, y: string}) {
	return '${id},${name}';
}

var x = {x:1, y:'abc'};
console.log(f(x)); // 1 abc
```

## spread operator

可変長の変数を配列に変換

```typescript
f(1,2,3);

function f(...args: string[]) {
	console.log(args); // [1,2,3]
}
```

逆(配列を可変長)もできる

```typescript
var x = [1,2,3];
f2(...x);

function f2(a,b,c) {
 	console.log(a); // 1
 	console.log(b); // 2
 	console.log(c); // 3
}
```

## for...of

普通のJavaScriptの`for...in`はプロパティ名が返る。

```typescript
for (var i in ['a','b','c']) {
	console.log(i);
}
// 0,1,2
```

`for...of`は値が返る。

```typescript
for (var i of ['a','b','c']) {
	console.log(i);
}
// 'a','b','c'
```