如何在typescript中键入一个动态加载其自己的成员的类

时间:2017-01-09 13:38:30

标签: javascript class typescript types

您好我使用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)返回类型error。 Foo上不存在key1

我在类上使用了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);

2 个答案:

答案 0 :(得分:1)

可能有更好的方法可以做到这一点,但这里有一些事情可以开始。

您可以使用2.1中添加的 mappedTypes 来创建基于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
    }

答案 1 :(得分:0)

这可以基于@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);