TypeScriptの基礎をシンプルに紹介する
はじめに
「JavaScriptは理解してるけどTypeScriptはそんなに」という方が対象です。
ES2015のJavaScriptに含まれる or 複雑な項目に関しては除外します。
TypeScriptとは
JavaScriptに型システムを備えた拡張言語。
JavaScriptのコードはほとんどそのまま動作する。
データ型
プリミティブ型
数値型(number)…1,2,3
文字列型(string)…'hoge', 'fuga'
真偽型(boolean)…true, false
シンボル型(symbol)…値が同一、かつ初期化の場所も同じ
オブジェクト型
配列型、タプル型、クラス型、インターフェイス型、関数型...etc
→ 後述する
型なし
any…任意の型
変数宣言
変数名の横に「:型」という形式で設定する。
let name:string = 'hoge'
let age:number = 100
let flg:boolean = true
型推論
変数宣言で型が省略された場合は、初期値から型を類推する。
let data = 100
data = 200
data = 'hoge' // NG
型アサーション
互換性のある型であれば、型を明示的に変換できる。
let age:string = <string>30
let age:string = 30 as string
配列
配列型
以下の例では、numberが要素のデータ型
let arrayData:number[] = [1,2,3,4,5]
let arrayData:number[][] = [[1,2],[3,4]] // 多次元配列
連想配列型
以下の例では、numberがインデックスのデータ型、stringが値のデータ型
let objData:{[index:number]:string} = {
1:'ほげ',
2:'ふー',
3:'ばー'
}
タプル型
複数の型が混在した配列
let tuple: [string, number, boolean] = ['dog', 100, true]
列挙型
列挙型は関連する定数を束ねる役割を担う。
以下の例では、MALEなどの各項目が「列挙子」となる。
列挙子に値を割り当てない場合、デフォルトで0から順に数値が割り振られる。
enum Animal {
DOG = 1,
CAT = 5,
MONKEY = 10
}
関数
関数型では引数と戻り値の型を定義できる。
void
値がないことを意味する型
function hoge (name:string): void {
console.log('hoge')
}
never
終点まで辿り着かないことを意味する型 → 例外スロー、無限ループ等
function huga (name:string): never {
while (true) {
console.log('huga')
}
}
オーバーロード
同じ名前だが引数や戻り値が異なる関数を定義すること
以下の例では、引数の型としてstringとnumberが許容される。
// 引数の型が異なる
function hoge (value:string):void
function hoge (value:number):void
function hoge (value:any):void {
// 型ガード(変数の型を特定)して処理を実行
if (typeof value === 'string') {
// 引数がstringの時の処理
} else{
// 引数がnumberの時の処理
}
}
共用型(ユニオン型)
複数の型の中のどれかを表す型
let data: string | number
リテラル型
リテラルがそのまま型として使用される。
以下の例では、'march'や'april'などを共用型で連結し、
型エイリアスでspringという別名を付与している。
type spring = 'march' | 'april' | 'may'
type dice = 1 | 2 | 3 | 4 | 5 | 6
型エイリアス
特定の型に別名を設定する仕組み
type hogeType = [string, number, boolean]
let data:hogeType = ['aaa', 'bbb', 100, true]
クラス
ES2015以降使えるクラスと機能は似ているが、
TypeScriptにだけ備わっている機能を紹介する。
型アノテーション
プロパティやメソッド内の引数・戻り値などで型を使用できる。
アクセス修飾子
プロパティ/メソッドにアクセスの可否レベルを設定できる。
public…クラスの外からアクセス可能
protected…同じクラスか継承されたクラスからアクセス可能
private…クラス内からアクセス可能
readonly
フィールドを読み取り専用にする
class Person {
private name:string
protected age:number
constructor (name:string, age:number) {
this.name = name
this.age = age
}
public hoge():string {
return`${this.name}は${this.age}歳です。`
}
}
インターフェイス
全てのメソッドが抽象メソッドである特別なクラス。
全てのメソッドが抽象メソッドなので、abstract修飾子は指定できない。
全てのメンバーがpublicなので、アクセス修飾子は指定できない。
staticメンバーも宣言できない。
interface Hoge {
foo(): number
}
継承
クラスは単一継承しかできないが、インターフェイスは複数継承が可能。
インターフェイスを継承して、新たなインターフェイスを宣言できる。
interface Hoge extends aaa, bbb {
foo(): number
}
クラスを継承して、インターフェイスを宣言することもできる。
その場合、クラスの実装は無視されてシグニチャだけが継承される。
class HogeClass {
aaa () {...}
}
interface Hoge extends HogeClass {
aaa () {...}
}
型注釈として使う
オブジェクト、関数、メソッドなどで使用できる。
// オブジェクト
interface ccc {
name?: string; // 省略可能
readonly age: number
}
let person:ccc = {
name: 'Mike'
}
// 関数
interface ddd {
(a: string, b:number): string
}
let plus: ddd = function (x:string,y:number):string {
return x + y // 仮引数の名前は異なっても問題ない
}
おわりに
基本的な項目に絞って紹介しました。
本記事で触れなかった部分として、構造的部分型という概念があります。
これはとても重要なので説明ページのリンクを貼っておきます。
サバイバルTypeScript
Discussion