【问题标题】:How do I type a class in typescript that dynamically loads its own members如何在打字稿中键入一个动态加载其自己成员的类
【发布时间】:2017-05-23 19:01:07
【问题描述】:

您好,我正在使用typescript 2.1.4,但我遇到了这个问题。

想象一下我有一个看起来像这样的object

interface IObj{
    key1:ISubObj;
}
interface ISubObj{
    exp:RegExp;
    method:(param:string)=>boolean
}
const obj:IObj={
    key1: {
        exp: /someexp/i,
        method: somemethod
    }
}

somemethod 看起来像这样

function somemethod(regexp){
   return function(param){
       return regexp.test(param)
   }
} 

在类型脚本中我创建了一个看起来像这样的类

export class someClass {
 constructor(obj) {
    for (let k in obj) {
        this[k]=obj[k].method(obj[k].exp)
    }
    return this;
 }
}
export const Foo = new someClass(obj);

我遇到的问题是它解析为有效的javascript 但是,使用Foo.key1(param) 返回一个类型errorkey1 在 Foo 上不存在。

我在课堂上使用了implements someInterface,但只有当我使用key1 作为可选时,接口才有效。我宁愿不使用可选语法

interface someInterface {
    key1?:(param:string)=>boolean
}
export class someClass implements someInterface{...}

有没有办法在动态构造的类上创建有效类型?

编辑

更正了 obj 未传递给构造函数的错字

编辑

使用@toskv 回答我稍微改变了我的解决方案以获得我想要的有效的。虽然这可能不是最好的方法

interface IObj{
    key1:ISubObj;
}
interface ISubObj{
    exp:RegExp;
    method:(param:string)=>boolean
}
const obj:IObj={
    key1: {
        exp: /someexp/i,
        method: somemethod
    }
}
export interface ISomeClass{
   key1:(str:string)=>boolean;
}
export type TSomeClass<T> = {
    [P in keyof T]?=T[P]
}
export class someClass {
 constructor(obj) {
    for (let k in obj) {
        this[k]=obj[k].method(obj[k].exp)
    }
    return this;
 }
}
export const Foo:TSomeClass<ISomeClass> = new someClass(obj);

【问题讨论】:

  • obj 是否有特定类型的类型或者可以是任何类型?
  • @toskv obj 将继续遵循相同的模式,因此它将按照您看到的方式输入。我编辑显示 obj 类型;
  • btw.. 这可能不是问题,但是.. 你实际上并没有将 obj 传递给构造函数。 :)

标签: javascript class typescript types


【解决方案1】:

可能有更好的方法来做这件事,但这里有一些开始。

您可以使用 2.1 中添加的 ma​​ppedTypes 来创建基于 IObj 接口的新类型。

interface IObj {
  key1: ISubObj;
}
interface ISubObj {
  exp: RegExp;
  method: (param: string) => boolean
}

type Result = {
  // must be optional so we can initialize it with nothing
  [P in keyof IObj]?: boolean
}

class Mine {
  // it's not really a property of the class but hey it's typed
  public results: Result = {};

  constructor(obj: IObj) {
    for (let k in obj) {
      this.results[k] = obj[k].method(obj[k].exp)
    }
    return this;
  }
}

// autocomplete and everything
new Mine(null).results.key1 

Here 是操场上的一个例子。

您可以在2.1 release notes 中阅读有关映射类型的更多信息。

在这种情况下,类并没有真正的意义。转换数据的函数同样有效。

function testIObj(obj: IObj): Result {
  let results: Result = {};
  for (let k in obj) {
    results[k] = obj[k].method(obj[k].exp)
  }
  return results;
}


testIObj(null).key1;

这使您可以做一些不错的事情,例如轻松处理它们的整个列表。

如果您的 方法 函数将返回不同的类型,那么扩展以适应它们也相对容易。

 type Result = {
      // must be optional so we can initialize it with nothing
      [P in keyof IObj]?: boolean | number
    }

【讨论】:

  • 这在您的情况下作为一个函数效果很好,但是有两个问题。一个 -> 我试图保留简单的命名空间 Foo.key1() 和两个 -> [P in keyof IObj]?: boolean 实际上应该是 `[P in keyof T]?:T[P]` 以减少混乱和更加动态。但这会导致其他接口更加复杂。我试图实现你的解决方案,但它不是很可扩展......
  • 查看类的构造函数中的代码,属性值将是从 IObject 接口调用方法函数并返回布尔值的结果,因此结果值的类型也是布尔值(除非这些方法可能会返回其他东西,我认为这没什么问题)。至于 Foo.key1() .. 我想如果你不使用类但只有一个函数可以创建定义类型的东西(并非所有东西都必须是类)。
  • 我同意“并非所有东西都需要成为一个类”,但我有一些计划,使用类可能有助于组织结构。这是我的方法的最简单版本...更多 @toskv
【解决方案2】:

这可以根据@toskv 的回答来工作。除了必须更新两个接口之外,您是否发现了这方面的问题?

interface IObj{
    key1:ISubObj;
}
interface ISubObj{
    exp:RegExp;
    method:(param:string)=>boolean
}
const obj:IObj={
    key1: {
        exp: /someexp/i,
        method: somemethod
    }
}
export interface ISomeClass{
   key1:(str:string)=>boolean;
}
export type TSomeClass<T> = {
    [P in keyof T]?=T[P]
}
export class someClass {
 constructor(obj) {
    for (let k in obj) {
        this[k]=obj[k].method(obj[k].exp)
    }
    return this;
 }
}
export const Foo:TSomeClass<ISomeClass> = new someClass(obj);

【讨论】:

  • 为什么要上课呢?除了创建这些东西的方法之外,someClass 上还有其他方法吗?
  • 另外请记住 T[P] 实际上是类型 (param: string) => boolean。因为它没有正确描述实际值是什么(即布尔值)。
猜你喜欢
  • 2013-02-26
  • 2020-05-21
  • 2021-12-29
  • 1970-01-01
  • 2019-12-05
  • 2019-11-28
  • 2020-06-29
  • 2019-10-23
  • 2020-03-09
相关资源
最近更新 更多