Honmushi blog
TypeScriptを学ぶ 型定義の基礎2019/10/21

TypeScriptを学ぶ 型定義の基礎

ReactNativeでのアプリ開発や、Gyatsbyでブログ作る際に何度か目にしたことのある「TypeScript」です。

最近よく目にしますが、どういった仕様や機能があるのかを把握しきれてないので、一度学んでまとめてみます。
目標としてはReactNativeでのアプリ開発、並びにGyatsbyでのブログ構築をjsからTypeScriptに置き換えていくことを考えています。

とりあえずここではデータ型の指定方法のみまとめてます。続きも学んで行き次第残していく予定です。

概要

  • TypeScript
  • 型を定義する
  • 名前付き関数のデータ型を定義
  • 関数のデータ型を定義
  • データ型定義の方法

TypeScript

JavaScriptに型を定義できることが大きな特徴。
型を定義してデプロイ前に静的にチェックできることなどが強み。

大人数での開発なんかではルールを定義することで保守性などに優れた堅牢なシステムが作れると思います。

準備とコンパイル

npmなどでTypeScriptをインストールすれば利用できます。

jsとの連携が簡単で、TypeScriptからjsを読み込んで利用することが出来ます。文法も踏襲されたものになっているのですぐに使い始めることが出来ます。

ちなみに「tsc」というコマンドを実行することで、CUIでTypeScriptからjsにビルド出来ます。 実際の開発では使うことはないと思いますが、仕組みの理解ために試してみると良さそうです。

型を定義する

変数の型を定義する

早速一番メジャーな機能である型定義を試してみます。

// TypeScriptは 「let」を使う。jsへの変換時にvarになる
// let 名前 : データ型 = 初期値;
// let 名前 : データ型;
// let 名前 = 初期値;

let sample : number = 0;

初期値を与えなかった場合はundefinedになります。 データ型を指定しなかった場合は初期値から型推論を行い使用されます。
定義してある型に一致しないデータが挿入されるプログラムになっているとビルド時にエラーがでます。

型を指定しなかった場合「any」として扱われ、通常のjsと同様に型推論が行われて動的に型付けされます。

let sample : any;
let sample ;

配列で型を定義する

配列の要素の型を定義します。指定しない場合はanyとなります。

//let array1 : Array<要素のデータ型> = [1,2,3,4]
let array1 : Array<number> = [1,2,3,4];

//let array2 : 要素のデータ型[] = [1,2,3,4]
let array2 : number[] = [1,2,3,4];

連想配列(Map)で型を定義する

連想配列の型指定です。Mapを使う場合になります。

// let 変数名 = new Map<キーのデータ型, 値のデータ型>()
let renso = new Map<string,number>([
    ["a",1],
    ["b",2],
    ["c",3],
    ["d",4],
]);

// let 変数名 : Map<キーのデータ型,値のデータ型> = new Map();

連想配列(Object)で型を定義する

Objectで連想配列を用意する場合になります。

// let 変数名 : {[key:string] : 値のデータ型 } = {} 
let renso2: {[key:string] : number } = {
    "a" : 1,
    "b" : 2,
    "c" : 3,
    "d" : 4,
}; 

クラスオブジェクトで連想配列の型を定義する

クラスを使ってデータ型を定義する場合です。

class Sample{
    Name : string;
    No: number;
}

let member : {[key:string]: Sample} = {
    "a" : {Name:'yamada', No:1},
    "b" : {Name:'yoshida', No:2},
    "c" : {Name:'yamamoto', No:3},
    "d" : {Name:'yasuda', No:4},
}

関数のデータ型を定義

名前付き関数のデータ型を定義

関数の引数と戻り値のデータ型を定義できます。

// function 関数名 (引数名1:データ型, 引数名2:データ型) : 戻り値のデータ型 {
//     処理
// }
function getName (id:number,type:string) : string {
    処理
}

戻り値はvoidを指定することで、戻り値なしを定義できます。

function notDo (id:number,type:string) : void{
    処理
}

匿名関数のデータ型の定義

基本ラムダ型を使えば良い。jsへの変換後は匿名関数に変換されているそうです。 理解のために念の為書いておきます。

// let 関数の変数名 = function (引数名1:データ型, 引数名2:データ型): 戻り値のデータ型 {
//    処理
// }

ラムダ式のデータ型の定義

ラムダ式の場合は先に引数、戻り値のデータ型を記述しておくこともできます。 その場合は関数の内容を記述する際にデータ型の定義を省略できます。

// 処理とデータ型を同時に定義する
// let ラムダ式の変数名 = (引数名1:データ型, 引数名2:データ型): 戻り値のデータ型 => {
//     処理
// }

// 1.処理を定義せずデータ型のみを先に定義する
// let ラムダ式の変数名 : (引数名1:データ型, 引数名2:データ型) => 戻り値のデータ型;
// 
// 2.処理を定義
// ラムダ式の変数名 = () => {
//     処理
// }

戻り値がない場合はvoid 処理が戻らない場合はnever

処理が終わって何も返さない場合は「void」を定義します。 無限にループする場合など、処理が変えることがない場合は「never」を戻り値の型として定義します

function notEnd (id:number,type:string) : never{
    処理
}

データ型定義の方法

値の組 Tuple を使う

シンプルな値の組の定義の場合はTupleを利用できます。 Tupleを用いることでクラスの定義をしなくても、値の組み合わせを定義することができます。
値の数と順番を定義でき、後から追加したり削除したりされることを防ぐことができます。

// let 変数名 : [データ型1,データ型2, ・・・] = []
let data1 : [string,string,nomber] = [ "apple", "bus", 20 ];
// 
// function 関数名 ( 引数 ) : [ データ型1, データ型2, ・・・] {
//    処理 
// }

データ型の候補を複数定義 共用体 Union

データ型の定義として、「どちらか」「どれか」一方という定義ができます。
変数はもちろん、関数の引数・戻り値でも使用可能です。関数内では typeof(prop) で型を取得するなどして条件分岐すると良さそうです。

// let 変数名 : データ型1 | データ型2 ;
let data : string | number | Date ;

null 許容型

データ型 | nullで定義すればnullになり得る共用体にできます。 このときには 変数名 || 変数の値がnullの場合の使用値という書き方ができます。

let text3 : string | null ;

console.info( text3 || "テキストなし" );

undefinedの許容

undefineedを許容することもできます。
関数の引数の場合は、引数名の後に?を付けることでundefinedの許容型にできます。

// let 変数名 : データ型 | undefined ;
// 
// function 関数名 ( 引数名? : 引数のデータ型){
//     処理
// };
// 
// function 関数名 ( 引数名 : 引数のデータ型 | undefined){
//     処理
// };

タグ付き共用体

データ型の定義クラスにタグをつけておくことで、itme.tagで確認できるようになります

//データ型を定義
class Person {
    tag : 'person';
    Name : string;
    No : number;
}
class Team {
    tag : 'team';
    Name : string;
    Color: string;
}

// type を使って 型の共用体に名前を付ける 型のエイリアス
type Item = Person | Team;

// 関数の引数として共用体を指定
function getData ( item : Item ) {
    switch (item.tag){
        case "person":
            return  // 処理
        case "team":
            return  // 処理
    }
}

交差型を使った合成 Intersection

2つ以上の型を合成して利用することも出来ます。

// let 変数名 : データ型1 & データ型2 ;

// 交差型は実際のクラスではないので、newは利用できない。`<交差型のエイリアス>`の書式なら指定可能
// let 変数名 = < データ型1 & データ型2 > {} ;

おわりに

今回はここまでにします。とりあえず型定義の基礎でした。
とりあえずデータ型の定義ができることはわかったので、アプリやサイトもすこしずつ修正していこうと思います。

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