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

Typescript 是否可以根据输入在注册表类上键入动态属性?,typescript,Typescript,我正在尝试将注册表对象移植到typescript。它具有基于传入对象属性的动态命名属性。我现在可能不会这样设计它,但是有大量的代码库在使用它,并且获得一个好的类型定义是改变它的开始 我怎样才能做到这一点?我获取[ts]元素隐式地具有“any”类型,因为类型“MyRegistry”没有索引签名。在forEach块中。如果无法键入,我如何更改将类型传递到注册表对象的方式,使其“可键入”?只要最终形状相同,我们就可以了 class MyNode { readonly name: string

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

我怎样才能做到这一点?我获取
[ts]元素隐式地具有“any”类型,因为类型“MyRegistry”没有索引签名。
在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)

下面的示例首先考虑使用
{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()
type RegistryItems={[n:string]:MyNode | MyInterface};
类MyRegistryBase{
构造函数(项:RegistryItems){
对象。分配(此,项);
}
otherMethod(){}
}
让MyRegistry:{new(items:T):MyRegistryBase&T}=MyRegistryBase;
常量a=新的MyNode('a')
常量b=新的MyNode('b')
常量c=新的MyNode('c')
const d=新的MyInterface('d')
常数e=新的MyInterface('e')
常量f=新的MyInterface('f')
const registry=new MyRegistry({a,b,c,d,e,f})
console.log(registry.a.name)
registry.otherMethod()

是否可以使
节点
接口
本身成为具有键值对而不是数组的对象?我之所以这样问,是因为有了这个签名,在编译时无法判断是否存在名称冲突,这使得
MyRegistry
上的任何索引签名在
MyNode
MyInterface
之间不明确。是的,但我没有收到其他错误。我尝试添加一个
[key:string]:任何
来消除错误,但不会使用数组或对象隐式键入成员。(至少在Object.values上循环)我认为您不能为
类定义允许推断特定属性类型的索引签名,但您可以定义一个通用的
[key:string]?:MyNode | MyInterfaceconst registry=Object.assign({},{d,e,f},{a,b,c})
将正确推断所有属性,但我假设
MyRegistry
具有示例代码中未提供的其他功能。