首页 > 解决方案 > 是否可以根据输入在注册表类上键入动态属性?

问题描述

我正在尝试将注册表对象移植到打字稿。它具有基于传入对象的属性的动态命名属性。我现在可能不会这样设计它,但是有大量代码库按原样使用它,并且围绕它获得一个好的类型定义是改变它的开始。

我怎样才能使这项工作?我进入[ts] Element implicitly has an 'any' type because type 'MyRegistry' has no index signature.了 forEach 块。如果无法输入此内容,我该如何更改将类型传递到此注册表对象的方式以使其“可输入”?只要最后的形状是一样的,我们就可以了。

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)

标签: typescript

解决方案


以下示例从仅用{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()

推荐阅读