2017-05-26 4 views
1

私の個人的なプロジェクトの1つでは、オブジェクトとリストの種類をいくつか設計しようとしていました。オブジェクトとリストは直列化可能であると考えられています(すなわち、toJSON()fromJSON()メソッドを持っています)。私が働いているすべてのオブジェクトとリストは、少なくとも方法ここに記載されているTypescript :: Abstract static

type IPerson = { 
    id: number; 
    name: string; 
    // additional properties 
} 

class Person { 
    id: number; 
    name: string; 
    // additional properties 
    constructor(id: number, name: string, ...) { ... } 
    toJSON(): IPerson { return { ... } } 
    static fromJSON(json: IPerson): Person { return new Person(...) } 
    // additional methods 
} 

class PersonList { 
    list: Person[]; 
    constructor(list: Person[]) { ... } 
    findById(id: number) { return this.list.find(it => it.id === id) } 
    findByName(name: string) { return this.list.find(it => it.name === name) } 
    add(person: Person) { this.list.push(person) } 
    remove(person: Person) { this.list = this.list.filter(it => it !== person) } 
    toJSON(): IPerson[] { return this.list.map(it => it.toJSON()) } 
    static fromJSON(json: IPerson[]): PersonList { return new PersonList(json.map(it => Person.fromJSON(it))) } 
    // additional methods 
} 

:サンプルオブジェクトとリストは以下の基本的なコードを持っているでしょう。 (それはしない)、それはこのように私の人生は同じくらい簡単になるだろう

type JSON = { 
    id: number; 
    name: string; 
} 

abstract class BaseObject<T extends JSON> { 
    abstract get id(); 
    abstract get name(); 
    constructor(id: number, name: string) { ... } 
    abstract toJSON(): T 
    abstract static fromJSON(json: T): BaseObject<T> 
} 

class BaseList<T, U> { 
    list: BaseObject<T>[]; 
    constructor(list: BaseObject<T>[]) { ... } 
    findById(id: number) { return this.list.find(it => it.id === id) } 
    findByName(name: string) { return this.list.find(it => it.name === name) } 
    add(obj: BaseObject<T>) { this.list.push(obj) } 
    remove(obj: BaseObject<T>) { this.list = this.list.filter(it => it !== obj) } 
    toJSON(): U[] { return this.list.map(it => it.toJSON()) } 
    static fromJSON(json: U[]): BaseList<T, U> { return new BaseList<T, U>(json.map(it => BaseObject<T>.fromJSON(it))) } 
} 

この構築物は働いていた場合::

は今、私は一般的なソリューションようにこれを変換しようとしている

type IPerson = JSON & { 
    // additional fields 
} 

class Person extends BaseObject<IPerson> { 
    get id() { ... } 
    get name() { ... } 
    // additional getters for other fields 
    toJSON(): IPerson { return { ... } } 
    static fromJSON(json: IPerson): Person { return new Person(...) } 
    // additional methods 
} 

class PersonList extends BaseList<Person, IPerson> { 
    // additional methods 
} 

// other object and list types definitions follow 

はしかし、私の解決策は、これらの点で失敗:

  1. BaseObjectは抽象静的を持つことができません方法。
  2. BaseListは、抽象的なスタティックfromJSON()メソッドを持つことはできません。
  3. BaseList.fromJSON()は新しいリストをインスタンス化することはできず、BaseObject.fromJSON()を呼び出して新しいオブジェクトをインスタンス化することもできません。

どうすればこれらの問題を回避できますか?ここで欠けているより良いデザインパターンがありますか?

答えて

0

私は、静的な抽象関数を定義することはできませんので、ここで私はに頼ってきた実装です:

type BaseJson = { 
    id: string; 
} 
abstract class BaseObj<U> { 
    abstract get id(): string; 
    abstract toJSON(): U; 
} 
abstract class BaseList<T extends BaseObj<U>, U> { 
    list: BaseObj<U>[] = []; 
    add(x: BaseObj<U>) { this.list.push(x) } 
    remove(x: BaseObj<U>) { this.list = this.list.filter(it => it !== x) } 
    toJSON(): U[] { return this.list.map(it => it.toJSON()) } 
} 

type IPerson = BaseJson & { 
    name: string; 
} 
class Person extends BaseObj<IPerson> { 
    data: IPerson; 
    constructor(data: IPerson) { super(); this.data = data } 
    get id() { return this.data.id } 
    get name() { return this.data.name } 
    toJSON(): IPerson { return { id: this.id, name: this.name } } 
    static fromJSON(json: IPerson): Person { return new Person(json) } 
} 
class PersonList extends BaseList<Person, IPerson> { 
    constructor(list: Person[]) { super(); this.list = list } 
    static fromJSON(json: IPerson[]): PersonList { return new PersonList(json.map(it => Person.fromJSON(it))) } 
} 

ボトムライン:私はすべてのオブジェクトと、リスト内の静的fromJSON()メソッドを定義する必要がありますクラス。これらの方法は複雑ではありませんので、快適なwin-winです。 =)