golangの日記

Go言語を中心にプログラミングについてのブログ

TypeScript classで型を限定したオブジェクト

typescript.png


やりたいこと。
TypeScript で型を限定したオブジェクトを作りたい。それにメソッドをつけたい。



ただのクラスはオブジェクトとして扱えない。コンパイルエラー

class StringObject {}

let o = new StringObject();
o.foo = 'value-1'; // エラー
o.bar = 'value-2'; // エラー
o.baz = 'value-3'; // エラー


型を指定するとオブジョクトとして扱うことができる。

class StringObject {
    [k: string]: string
}

let o = new StringObject();
o.foo = 'value-1';
o.bar = 'value-2';
o.baz = 'value-3';





classで作ったオブジェクトにメソッドをもたせる。


  1. スタティックメソッドで実装する。Object.keys(o) などと同じような使い方になる。
class StringObject {
    [k: string]: string;

    constructor(o?: {[k: string]: string}) {
        for (let k in o) {
            this[k] = o[k];
        }
    }

    public static values(o: StringObject): string[] {
        let a: string[] = [];
        for (let a in o) {
            a.push(o[k]);
        }
        return a;
    }
}

let o = new StringObject({foo : 'value-1', bar : 'value-2', baz : 'value-3'});

let a = StringObject.values(o);
console.log(a); // [ 'value-1', 'value-2', 'value-3' ]



  1. オブジェクトの値の型を any で妥協すると o.values(); のようにインスタンスメソッドで使える。
class StringObject {
    [k: string]: any;

    constructor(o: {[k: string]: any}) {
        for (let k in o) {
            this[k] = o[k];
        }

        const dispatcher = {
            enumerable : false,
            configurable : false,
            writable : false,
            value : () => {
                let a: string[] = [];
                for (let k in this) {
                    a.push(this[k]);
                }
                return a;
            }
        };

        Object.defineProperty(this, 'values', dispatcher);
    }
}

let o    = new StringObject();
o.foo    = 'value-1';
o.bar    = 'value-2';
o.baz    = 'value-3';
// o.values = 'value-4'; // 上書きはできないのでエラー

let a = o.values();

// 列挙しないように enumerable: false を設定したので values 自身は含まれない
console.log(a); // [ 'value-1', 'value-2', 'value-3' ]