【问题标题】:Typescript :: Abstract static打字稿::抽象静态
【发布时间】:2017-10-27 01:06:04
【问题描述】:

在我的一个个人项目中,我尝试设计一些对象和列表类型。对象和列表应该是可序列化的(即具有toJSON()fromJSON() 方法)。示例对象和列表将具有以下基本代码:

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 不能有抽象静态 fromJSON() 方法。
  2. BaseList 不能有抽象静态 fromJSON() 方法。
  3. BaseList.fromJSON() 不能实例化一个新的列表,也不能调用BaseObject.fromJSON() 来实例化一个新的对象。

如何规避这些问题?我在这里缺少更好的设计模式吗?

【问题讨论】:

标签: generics typescript inheritance


【解决方案1】:

由于我无法定义静态抽象函数,因此我采用了以下实现:

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() 方法。这些方法并没有那么复杂,所以它是一个舒适的双赢。 =)

【讨论】:

  • 您介意解释一下您的解决方案吗?我认为这可能会增加您的回答的帮助。
猜你喜欢
  • 2017-09-29
  • 2021-09-26
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
相关资源
最近更新 更多