是否可以根据输入在注册表类上键入动态属性?

时间:2018-09-20 18:29:40

标签: typescript

我正在尝试将注册表对象移植到Typescript。它具有基于传入对象的属性而动态命名的属性。我现在可能不会以这种方式设计它,但是有大量的代码库按原样使用它,并且围绕它获得良好的类型def是对其进行更改的开始。

我该如何进行这项工作?我在forEach块中得到[ts] Element implicitly has an 'any' type because type 'MyRegistry' has no index signature.。而且,如果无法键入此内容,如何更改将类型传递到此注册表对象中的方式,使其可以“键入”?只要最后的形状相同,就可以了。

class MyNode {
  readonly name: string
  constructor(name: string) {
    this.name = name
  }
}

class MyInterface {
  readonly name: string
  constructor(name: string) {
    this.name = name
  }
}

class MyRegistry {
  constructor({ nodes, interfaces }: { nodes: MyNode[], interfaces: MyInterface[]}) {
    nodes.forEach(node => {
      this[node.name] = node
    })
    interfaces.forEach(interfaces => {
      this[interfaces.name] = interfaces
    })

  }
}

const a = new MyNode('a')
const b = new MyNode('b')
const c = new MyNode('c')

const d = new MyInterface('d')
const e = new MyInterface('e')
const f = new MyInterface('f')

const registry = new MyRegistry({
  nodes: [a, b, c],
  interfaces: [d, e, f]
})

console.log(registry.a.name)

1 个答案:

答案 0 :(得分:1)

下面的示例从仅使用{a, b, c, d, e, f}作为注册表的想法开始,但是也保留了注册表的其他方法:

type RegistryItems = { [n: string]: MyNode | MyInterface };

class MyRegistryBase {
  constructor(items: RegistryItems) {
    Object.assign(this, items);
  }

  otherMethod() { }
}

let MyRegistry: { new <T extends RegistryItems>(items: T): MyRegistryBase & T} = <any>MyRegistryBase;

const a = new MyNode('a')
const b = new MyNode('b')
const c = new MyNode('c')

const d = new MyInterface('d')
const e = new MyInterface('e')
const f = new MyInterface('f')

const registry = new MyRegistry({a, b, c, d, e, f})

console.log(registry.a.name)
registry.otherMethod()