トップ 差分 一覧 ping ソース 検索 ヘルプ PDF RSS ログイン

TypeScript


RSS 無料英単語

目次



記事一覧

キーワード

TypeScript

[Node.js]


 準備

install

> npm install -g typescirpt

init

tsconfig.json の生成
> tsc --init

Visual Studio Code タスク

F1 - task run - build tsconfig.json

変数・型

 変数・定数

変数宣言 ブロックスコープ 同じスコープでの重複宣言 備考
var 認識しない 認める
let 認識する 認めない
const 認識する 認めない 再代入不可

 

説明
number 数値
string 文字列
boolean 真偽
symbol シンボル
any 任意
オブジェクト

 文字列リテラル

`バッククオートで囲む

  • 改行もそのまま
  • ${...} ...に変数、式を埋め込み
class Program {
    static main() {
        let name: string = "Hiroto Yagi";
        let age = 46;   // 型推論
        // age = "Hello"; // 数値型に文字列代入エラー
        let msg = null; // 初期値未指定、null指定など、any型と類推され型チェックは働かない
        msg = 100;      // noImplicitAny:true とすると、暗黙的 anyは許容しない
        msg = "Hello";
    
        // テンプレート文字列
        console.log(`
        ${msg} 
        my name is ${name} 
        age ${age}
        ${new Date()}`);
    }
}

Program.main();
結果
> node ./src/app.js

       Hello
       my name is Hiroto Yagi
       age 46
       toda Tue Nov 07 2017 18:59:23 GMT+0900 (東京 (標準時))

 型アサーション

  • キャスト
function show(message: string) {
    console.log(`${message}`);
}
class TypeAssartion {
    static main() {
        // show(10);    // ERROR
        show(<any>10);  // OK
        show(10 as any); // as もOK
    }
}

 コレクション/インターフェース

interface StringMap {
    [index:string]:string;
}
class Collection {
    static main() {
        // 配列
        let languages: string[] = ['java','C#','python'];
        console.log(languages);

        // 連想配列
        let fwMap: {[key:string]:string} = {
            'java':'Spring',
            'C#':'Asp.net',
            'python':'Django'
        };
        console.log(fwMap);

        // インデクスシグネチャはinterfaceとして事前定義可
        let fwMap2: StringMap = {
            'java':'Spring',
            'C#':'Asp.net',
            'python':'Django'
        };
        console.log(fwMap2);
    }
}

 列挙

enum Animal {
    DOG,
    CAT,
    MOUSE,
    ELEPHANT
}
enum Fruit {
    APPLE = "A",
    ORANGE = "O",
    PAINAPPLE = "P"
}
class EnumSample {
    static main() {
        let mypet: Animal = Animal.DOG;
        // デフォルトで0からの数値が割り当てられる
        console.log(mypet);
        console.log(Animal[mypet]);
        
        let myfavarit: Fruit = Fruit.PAINAPPLE;
        // 列挙子に値を割り当てることも可能
        console.log(myfavarit);
    }
}
結果
0
DOG
P

 タプル

let tpl: [string, number, boolean] = ['Yagi', 46, true];
console.log(`name:${tpl[0]} age:${tpl[1]} marriged:${tpl[2]}`);

 共用型

let data: string | boolean;
data = 'foo';// OK
data = true; // OK
// data = 1; // NG

let datas: (boolean | number)[] = [true, false, 1, 0];

 型エイリアス

// 主にタプル、共用型に別名を付与。インターフェースでできる場合に使用しないほうがよい
type ProfileTuple = [string, number, boolean];
let me = ['yagi', 46, true];        
console.log(`name:${me[0]} age:${me[1]} marriged:${me[2]}`);

 文字列リテラル

type Season = 'spring' | 'summer' | 'autumn' | 'winter';
class StringLiteralType {
    printSeason(s: Season) {
        console.log(s);
    }
    static main() {
        let me = new StringLiteralType();
        me.printSeason('summer');  // OK
        // me.printSeason('hoge'); // NG
    }
}

関数

  • function命令
  • 関数リテラル
  • アロー関数

 関数、関数リテラル、アロー関数

function squire(x: number, y: number) :number {
    return x * y;
}
class FunctionSample{
    static main() {
        // 関数の使用
        console.log(squire(8,8));

        // 関数リテラル(型推論)
        let m3 = function(x :number, y: number, z: number): number {
            return x * y * z;
        } ;
        console.log(m3(8,8,8));

        // 関数リテラル(型明示)
        let m2: (x: number, y: number) => number = function(x: number, y: number) {
            return x * y;
        };
        console.log(m2(9,9));
        
        // アロー関数(ラムダ式)
        // this は宣言された場所によって変わる
        let m22 = (x: number, y: number): number =>  x * y;
        console.log(m22(5,5));
    }
}

 引数の省略、デフォルト引数、可変長引数

class FunctionApplySample {
    static main(){
        // TypeScriptでは宣言された引数はすべて必須
        // 引数を省略したい場合、仮引数の名前の後ろに ? を付与
        let greet = function(message?: string){
            message = (message === undefined)?"hello":message;
            console.log(message);
        }
        greet();
        greet("good evening");
    
        // 関数のデフォルト値を設定するには、仮引数の後に=デフォルト値
        // デフォルト値には、式も利用できる
        // 明示的に undefined を渡した場合もデフォルト値が利用される
        let greet2 = function(message: string=`hello ${new Date()}`) {
            console.log(message);
        }
        greet2();
        greet2("good night");
        greet2(undefined);

        // 可変長引数
        // 仮引数の前に、... とすることで可変長引数となる
        let sum = function(...nums: number[]):number {
            let ttl: number = 0;
            nums.forEach((value,index,array) => ttl += value);
            return ttl;
        }
        console.log(sum(1,2,3,4,5));
    }
}

 関数のオーバーロード

function showMessage(value: number): void;
function showMessage(value: boolean): void;
function showMessage(value: any): void {
    let message: string | undefined;
    if (typeof value === 'number') {
        message = `${value} is number.`;
    }
    if (typeof value === 'boolean') {
        message = `${value} is boolean`;
    }
    console.log(message);
}
class FunctionApplySample2 {
    static main(){
        console.log("*** 関数応用2 ***");
        // 1.シグネチャのみの関数を用意
        // 2.具体的な実装を直後に定義
        // 3.実装の中で、typeof/instanceof を用いて型を判定し処理を記述
        showMessage(123);
        showMessage(false);
        showMessage("Hello" as any);
    }
}

オブジェクト指向

 クラス定義

class Person {
    // メンバー
    name: string; // デフォルト public
    private _age: number; 

    // 静的メンバー
    public static CHEAT_AGES: number = 2;
    
    // コンストラクター
    constructor(name: string, age: number){
        this.name = name;
        this._age = age;
    }

    // 以下のコンストラクターでメンバーの宣言と代入を省略できる
    // アクセス修飾子必須
    // constructor(public name: string, private _age: number) {
    // }

    // アクセッサー
    get age(): number {
        return this._age - Person.CHEAT_AGES;
    }
    set age(value: number) {
        this._age = value;
    }

    // メソッド
    printProfile(){
        console.log(`name=${this.name},age=${this.age}`);
    }
}
console.log(Person.CHEAT_AGES);
let me = new Person('Yagi', 46);
//console.log(me.age); // NG
me.printProfile();
me.age = 50;
me.printProfile();
結果
2
name=Yagi,age=44
name=Yagi,age=48

 名前空間

  • namespace ブロックで定義
  • exportで外側からアクセス可能なことを明示
  • 完全修飾名で呼び出す
namespace NameA {
    export class Foo {
        name() {
            console.log("NameA.Foo");
        }
    }
    export function bar(){
        console.log("NameA.bar()");
    }
}
let foo = new NameA.Foo();
foo.name();
NameA.bar();

名前空間のネスト

namespace NameB {
    export namespace NameC {
        export function bar(){
            console.log("NameB.NameC.bar()");
        }
    }
}
NameB.NameC.bar(); 

 継承

class Guiter {
    constructor(public maker: string, public type: string){}
    print() {
        console.log(`${this.type} by ${this.maker}`);
    }
}
class Lespaul extends Guiter {
    constructor(){
        super("Gibson","Lespaul");
    }
}
(new Lespaul()).print();

 抽象クラス

// 抽象クラス
abstract class Viecle {
    // 抽象メソッド
    abstract getEngineDisplacement(): number;
    printDisplacement() {
        console.log(`${this.getEngineDisplacement()}`);
    }
}
class Premacy extends Viecle {
    // 抽象メソッドのオーバーライド
    getEngineDisplacement(): number {
        return 2000;
    }
    // メソッドオーバーライド
    printDisplacement() {
        console.log("******");
        super.printDisplacement();
        console.log("******");
    }
}
(new Premacy()).printDisplacement();

 インターフェース

interface Color {
    // メソッドはすべて抽象メソッド
    // abstract 指定は不要
    getRGB(): string;
}
class Red implements Color {
    getRGB(): string {
        return "#FF0000";
    }
}
console.log((new Red()).getRGB());

 構造的部分型(Structual subtyping)

class Hoge {
    constructor(public name: string, public age: number){}
}
class Spam {
    constructor(public name: string, public age: number){}
}
// 継承による明示的な互換性(Nominal subtyping)がなくても構造が一致していれば代入可能
let h: Hoge = new Spam("spam",10);
console.log(h);



YAGI Hiroto (piroto@a-net.email.ne.jp)
twitter http://twitter.com/pppiroto