技術めも

TypeScript


class User {
    // TODO
}

console.log("Hello");

------------------------------------------------------------
// 列挙型
// わかりやすく定数を表現

enum Signal {
    Red = 0,
    Blue = 1,
    Yellow = 2
}

enum Signal {
    Red,      // 0
    Blue = 3,
    Yellow    // 4
}

// 同じ列挙型はマージされる

var result: Signal; // 宣言

if (result === Signal.Yellow) { ... }
if (result === Signal['Yellow']) { ... }

console.log(Signal[2]); // Yellow

------------------------------------------------------------
// 静的型付け
// void

function add(a: number, b: number): number {
    return a + b;
}

// b がオプションの場合
function add(a: number, b?: number): number {
    if (b) {
        return a + b;
    } else {
        return a + a;
    }
}

// b に初期値を設定
function add(a: number, b: number = 10): number {
    return a + b;
}

------------------------------------------------------------
// 関数

var add = function(a: number, b: number): number {
    return a + b;
}

var add = (a: number, b: number): number => {
    return a + b;
}

// 最後に評価された値が return になる
var add = (a: number, b: number): number => a + b

------------------------------------------------------------
// 関数のオーバーロード

function add(a: number, b: number): number; // シグネチャ
function add(a: string, b: string): string;

function add(a: any, b: any) {
    if (typeof a === "string" && typeof b === "string") {
        return a + " " + b;
    }
    return a + b;
}

------------------------------------------------------------
// クラス
// アクセス修飾子 デフォルト public, private, protected

class User {
    name: string;

    constractor(name: string) {
        this.name = name;
    }

    saiHi(): void { // function は不要
        console.log("Hi I am " + this.name)
    }
}

var tom =  new User("Tom");
console.log(tom.name);
tom.sayHi();

------------------------------------------------------------
// Class

class User {
    public name: string;

    constractor(public name: string) { // クラス変数に保持
    }

    public saiHi(): void { // function は不要
        console.log("Hi I am " + this.name)
    }
}

------------------------------------------------------------
// getter, setter
// コンパイラーでオプション必要 「-t ES5」

constractor(private _name: string) {
}

get name() {
    return this.name;
}

set name(newName: string) {
    this._name = newName;
}

console.log(tom.name);
tom.name("papa");
console.log(tom.name);

------------------------------------------------------------
// クラスの継承

class AdminUser extends User {
    private _age: number;

    constractor(_name: string, _age: number) {
        super(_name);
        this._age = _age;
    }

    public sayHi(): void {  // メソッド オーバーライド
        console.log("my age: " + this._age);
        super.sayHi();
    }
}

------------------------------------------------------------
// 変数、メソッド → そのクラスの「メンバ」と呼ぶ
// 静的メンバ


class User {
    cnstractor(name: string) {
        this.name = name;
        User.count++; // ★
    }

    static count: number = 0; // ★

    static showDescription(): void { // ☆
        console.log("this is description");
    }
}

var tom = new User("Tom")
var bob = new User("Bob")
console.log(User.count); // ★

User.showDescription(); // ☆

------------------------------------------------------------
// Intardace

finction getTotal(result: {a: number, b: number}) { // 直書き
    return result.a + result.b;
}

var result = {a: 32, b: 58};

console.log(getTotal(result));

------------------------------

interface Result {
    a: number,
    b: number
}

finction getTotal(result: Result) { // インターフェイス
    return result.a + result.b;
}

var result = {a: 32, b: 58};

console.log(getTotal(result));

------------------------------
// 構造的部分型
// ある型のプロパティさえ持っていれば、その型として扱う

interface Result {
    a: number,
    b: number
}

finction getTotal(result: Result) { // インターフェイス
    return result.a + result.b;
}

var result = {a: 32, b: 58, c: "Hello"}; // ★ C が余計にあるけど問題なく処理される

console.log(getTotal(result));

------------------------------------------------------------
// インターフェイスは複数のインターフェイスから継承できる

interface FinalResult extends SpringResult, FallResults {
    final: number;
}

------------------------------------------------------------
// Interface -> Class

interface GameUser {
    score: number;
    showUser(): void;
}

class User implements GameUser {
    sore: number =0; // 必須
    howScore(): void { // 必須
    ……
}

------------------------------------------------------------
// Genrtics ジェネリック

function getStringArray(value: string): string[] {
    return [value, value, value]
}

function getNumberArray(value: number): number[] {
    return [value, value, value]
}

    ↓

function getArray<T>(value: T): return T[] {
    return [value, value, value]
}

console.log(getArray<number>(3));
console.log(getArray<string>("Hello"));

------------------------------------------------------------
// ジェネリック Class

class MyData<T> {
    constractor(public value: T) {}
    getArray(): T[] {
        return [this.value, this.value, this.value];
    }
}

var v1 = new MyData<string>("Hello");
console.log(v1.getArray());

var v2 = new MyData<number>(234);
console.log(v2.getArray());

------------------------------------------------------------
// ジェネリックに成約

interface Result {
    a: number,
    b: number
}

class MyData<T extends Result> { // 型は何でもいいが a, b 必須
    constractor(public value: T) {}
    getArray(): T[] {
        return [this.value, this.value, this.value];
    }
}

var v3 = new MyData<Result>({a: 32, b: 16}); // a, b さえ持ってればいい(構造的部分型)
console.log(v3.getArray());

------------------------------------------------------------
// 内部モジュール

module UserModule {
    export var name = "taguchi"; // export 外部に対して公開する
    export module AdressModule {
        var zip = "111-111";
    }
}

console.log(UserModule.name);
console.log(UserModule.AdressModule.zip);

import addr = UserModule.AdressModule; // 別名で定義
console.log(addr.zip);

// ------------------------------
// 別ファイル user.ts

/// <reference path="./user.ts" />

console.log(UserModule.name);
console.log(UserModule.AdressModule.zip);

→ js が2つできてしまうので、--out オプション
$ tsc main.js --out all.js

------------------------------------------------------------
// 外部モジュール
// Node - CommonJS
// RequireJS - AMD
// 1ファイル1モジュール

------------------------------
user_commonjs.ts
------------------------------
export var name = "taguchi";

------------------------------

import User = require("./user_common_js"); // 拡張子不要
console.log(User.name);

$ tsc main.ts -m commonjs
→ user_commonjs.js が作成

------------------------------
user_amd.ts
------------------------------
export var name = "taguchi";

------------------------------

import User = require("./user_amd"); // 拡張子不要
console.log(User.name);

$ tsc main.ts -m amd
→ user_amd.js が作成

http://dotinstall.com/lessons/basic_typescript

  • マイクロソフト
  • TypeScript -> JavaScript
  • 静的な型付け
  • クラスベースのオブジェクト指向

http://www.typescriptlang.org/

インストール

sudo npm install -g typescript

  • main.ts
class User {
    
}

console.log("hello world");
tsc main.ts
  → main.js

node main.js

変数の静的型付け <-> 動的型付け(type script)

// TypeScript

var x: number = 10;
x = "hello";

/*
number
string
boolean
any
*/

var i: number;
var i: number = 10;
var i = 10; // i: number

var x; // var x: any
x = 10;
x = "hello";

var results: number[];
results = [10, 5, 3];

列挙型(わかり易く定数を表現)

/*
enum Signal {
    Red = 0,
    Blue = 1,
    Yellow = 2
}
*/

enum Signal {
    Red, // 0
    Blue = 3,
    Yellow // 4
}

enum Signal {
    Green = 5   // マージされる
}

var result: Signal;

// if (result === Signal.Yellow) { ... }
// if (result === Signal['Yellow']) { ... }

// console.log(Signal[2]); // Yellow
// console.log(Signal[3]); // Blue

console.log(Signal.Green); // 5

関数 - 静的型付け

  • 返り値がない void
  • 引数がオプション b?
function add(a: number, b: number): number {
    return a + b;
}

function add(a: number, b?: number): number {
    // b が無かった場合
    if (b) {
        return a + b;
    } else {
        return a + a;
    }
}

function add(a: number, b: number = 10): number {
    return a + b;
}

// console.log(add(5, 3));
// console.log(add(5, "hello"));
console.log(add(5, 3));
console.log(add(5));

関数式

var add = function(a: number, b: number): number {
    return a + b;
}

// アロー関数式( => )
var add = (a: number, b: number): number => {
    return a + b;
}

// リターンも省略可能
var add = (a: number, b: number): number => a + b;

console.log(add(5, 3));

関数のオーバーロード

function add(a: number, b: number): number; // シグネチャ(関数の引数と返り値のコンビ)
function add(a: string, b: string): string;

function add(a: any, b: any): any {
    if (typeof a === "string" && typeof b === "string") {
        return a + " " + b;
    }
    return a + b;
}

// console.log(add(5, 3)); // 8
// console.log(add("hello", "world")); // hello world

console.log(add("hello", 3));

クラス

// public, protected, private アクセス修飾子

class User {
    public name: string;
    constructor(name: string) {
        this.name = name;
    }
          ↓
    // コンストラクタでメンバ変数定義&設定
    constructor(public name: string) {
    }

    public sayHi(): void {
        console.log("hi! i am " + this.name);
    }
}

var tom = new User("Tom");
console.log(tom.name);
tom.sayHi();

GETTER, SETTER

class User {
    // private に変更
    constructor(private _name: string) {
    }
    public sayHi(): void {
        console.log("hi! i am " + this._name);
    }

    // GETTER(tom.name で取得) - ECMA5の機能
    get name() {
        return this._name;
    }

    // SETTER(tom.name = "TOM"; で設定)- ECMA5の機能
    set name(newValue: string) {
        this._name = newValue;
    }
}

var tom = new User("Tom");
console.log(tom.name);
tom.name = "TOM";
console.log(tom.name);
tom.sayHi();

ECMA5 コンパイル

tsc main.ts -t ES5

クラス継承

// public, protected, private

class User {
    constructor(protected _name: string) {
    }
    public sayHi(): void {
        console.log("hi! i am " + this._name);
    }
}

// extends で継承
class AdminUser extends User {
    private _age: number;
    constructor(_name: string, _age: number) {
        super(_name);
        this._age = _age;
    }

    public sayHi(): void {
        console.log("my age: " + this._age);
        console.log("my name: " + this._name);
        // 親クラスの SayHi 実行
        super.sayHi();
    }
}

var bob = new AdminUser("Bob", 23);
bob.sayHi();

静的メンバ static

  • メンバ:そのクラスの変数やメソッド
  • インスタンスではなく、class に保持されるメンバ
class User {
    name: string;
    constructor(name: string) {
        this.name = name;
        User.count++;
    }

    sayHi(): void {
        console.log("hi! i am " + this.name);
    }

    static count: number = 0;

    static showDescription(): void {
        console.log("this class is about users");
    }
}

var tom = new User("Tom");
var bob = new User("Bob");
console.log(User.count);
User.showDescription();

Interface

オブジェクトの型に名前をつけるもの

構造的部分型
ある型のプロパティを持っていれさえすれば、その「型」としてみなす

interface Result {
    a: number;
    b: number;
}

// 変数の型付け
function getTotal(result: {a: number, b: number}) {
    ↓
function getTotal(result: Result) {
    return result.a + result.b;
}

var result = {
    a: 32,
    b: 58,
    c: "hello"  // 構造的部分型
};

console.log(getTotal(result));

Interface

複数インターフェイスを継承可能

interface SpringResult {
    a: number;
}

interface FallResult {
    b: number;
}

interface FinalResult extends SpringResult, FallResult {
    final: number;
    // final?: number; // オプション指定
}

function getTotal(result: FinalResult) {
    // オプションの確認
    if (result.final) {
        return result.a + result.b + result.final;
    } else {
        return result.a + result.b;
    }
}

var result = {
    a: 32,
    b: 58
};

console.log(getTotal(result));

インターフェイスの実装

Interface と Class を紐付ける

interface GameUser {
    score: number;
    showScore(): void;
}

class User implements GameUser {
    name: string;
    score: number = 0;            // 実装しないtぽ行けない
    constructor(name: string) {
        this.name = name;
    }
    sayHi(): void {
        console.log("hi! i am " + this.name);
    }
    showScore(): void {           // 実装しないtぽ行けない
        console.log("score " + this.score);
    }
}

ジェネリクス

Generics: 抽象化されたデータ型

function getStringArray(value: string): string[] {
    return [value, value, value];
}

function getNumberArray(value: number): number[] {
    return [value, value, value];
}
function getArray<T>(value: T): T[] {
    return [value, value, value];
}

console.log(getArray<number>(3));       // 呼び出し側で「型」を指定
console.log(getArray<string>("hello")); // 呼び出し側で「型」を指定

ジェネリクスに制約を付与

class MyData<T> {
    constructor(public value: T) {}
    getArray(): T[] {
        return [this.value, this.value, this.value];
    }
}

var v1 = new MyData<string>("hello");
console.log(v1.getArray());
var v2 = new MyData<number>(234);
console.log(v2.getArray());
interface Result {
    a: number;
    b: number;
}

class MyData<T extends Result> {
    constructor(public value: T) {}
    getArray(): T[] {
        return [this.value, this.value, this.value];
    }
}

var v3 = new MyData<Result>({a: 32, b: 16});
console.log(v3.getArray());
interface Result {
    a: number;
    b: number;
}

interface FinalResult {
    a: number;
    b: number;
    c: string;
}

class MyData<T extends Result> {
    constructor(public value: T) {}
    getArray(): T[] {
        return [this.value, this.value, this.value];
    }
}

// a, b を持っていればOKなので、FinalResult もOK(構造的部分型)
var v4 = new MyData<FinalResult>({a: 32, b: 16, c: "hello"});
console.log(v4.getArray());

内部モジュール

module UserModule {
    export var name = "taguchi";   // export:外部に対して公開する
    export module AddressModule {
        export var zip = "111-1111";
    }
}

console.log(UserModule.name);
console.log(UserModule.AddressModule.zip);

// 短い名前に出来る
import addr = UserModule.AddressModule;
console.log(addr.zip);

main.ts

// スラッシュ3つでモジュール読み込み
/// <reference path="./user.ts" />

console.log(UserModule.name);

import addr = UserModule.AddressModule;
console.log(addr.zip);

user.ts

module UserModule {
    export var name = "taguchi";
    export module AddressModule {
        export var zip = "111-1111";
    }
}

コンパイル

tsc main.js --out all.js

外部モジュールを使ってみよう

  • Node - CommonJS
  • RequireJS - AMD

1ファイルに1モジュール
→ よって module定義 はいらない

user_commonjs.ts、user_amd.ts

exports.name = "taguchi";

CommonJS 形式

import User = require("./user_commonjs");

console.log(User.name);

コンパイル

tsc main.ts -m commonjs // CommonJS形式

AMD 形式

import User = require("./user_amd");

console.log(User.name);

コンパイル (AND形式)

tsc main.ts -m amd // AND形式