创建通用类型实例的通用存储库

时间:2019-06-17 17:54:47

标签: typescript

我正在尝试在TypeScript中编写一个通用存储库,该存储库使用localStorage进行序列化/反序列化。

我在ts中已经阅读了许多related regarding new()个问题,但是它们充满了foos,bars和baze,我找不到真正的例子。最重要的是,我找不到一个可以在泛型类中创建新实例的示例(我发现的所有示例都假定类型是已知的,而您将在下面看到的存储库类中的类型是未知的)。

“狗”实体:

interface IEntity { }

class Dog implements IEntity {

  constructor(json: string);     // called when deserializing
  constructor(name: string, age: number);
  constructor(jsonOrName: string, age?: number) { /* implementation... */ }

  name: string;
  age: number;

  toJSON() {    // called when serializing (via JSON.stringify)
    //...
  }
}

还有一个用于从localStorage进行序列化/反序列化的存储库。

class Repository<T extends IEntity> {

  constructor(private key: string) { }

  read(): T | null {
    const s = localStorage.getItem(this.key);
    if (!s) return null;
    const value = JSON.parse(s);
    return new T(value);            // <----------- how do I do this?
  }

  write(value: T): void {
    localStorage.setItem(this.key, JSON.stringify(value));
  }

}

预期用途是:

const dogRepository = new Repository<Dog>("dog");
const dog = dogRepository.read();
if (dog) console.log(dog.name);

1 个答案:

答案 0 :(得分:2)

类型系统在运行时完全为erased,因此名为T的类型将不存在,因为您可以通过new运算符构造任何东西。相反,您需要Respository<T>实例来为T保留一个实际的运行时构造函数。例如:

class Repository<T extends IEntity> {

  // take a key *and* a constructor which operates on a json string
  constructor(private key: string, private ctor: new (json: string) => T) {}

  read(): T | null {
    const s = localStorage.getItem(this.key);
    if (!s) return null;
    return new this.ctor(s); // use the ctor on the JSON (don't parse, right?)
  }

  write(value: T): void {
    localStorage.setItem(this.key, JSON.stringify(value));
  }
}

然后您也必须更改此设置:

const dogRepository = new Repository("dog", Dog); // pass ctor here, T is inferred
const dog = dogRepository.read();
if (dog) console.log(dog.name);

这有意义吗?希望能有所帮助。祝你好运!

Link to code