如何在TS上为类构造函数的映射描述函数

时间:2019-07-08 09:10:06

标签: typescript

我尝试实现将包含类实例的JS Object返回为值并将类名称作为键的函数。

类似的东西:

const init = (construcorsMap) => {
    return Object.keys(construcorsMap).reduce((ret, constructorName) => {
         ret[constructorName] = new (construcorsMap[constructorName])();
         return ret;
     }, {});

class C1 {};
class C2 {};
const instances = init({C1: C1, C2: C2});

如何在TypeScript上标注它?

2 个答案:

答案 0 :(得分:2)

这可以使用InstanceType和自定义映射类型来完成。您将在实现中需要一些类型断言,但调用站点将完全是类型安全的

type InstanceTypes<T extends Record<keyof T, new () => any>> = {
    [P in keyof T]: InstanceType<T[P]>
}
const init = <T extends Record<keyof T, new () => any>>(construcorsMap: T): InstanceTypes<T>  => {
    return (Object.keys(construcorsMap) as Array<keyof T>).reduce((ret, constructorName) => {
        ret[constructorName] = new (construcorsMap[constructorName])();
        return ret;
    }, {} as InstanceTypes<T>);
}

class C1 { c1!: number};
class C2 { c2!: string};
const instances = init({C1: C1, C2: C2});
instances.C1.c1;
instances.C2.c2

实时副本on the playground

答案 1 :(得分:1)

您可以使用内置InstanceMap创建InstanceType类型:

type InstanceMap<C extends Record<string, new () => any>> = {
  [k in keyof C]: InstanceType<C[k]>
};

function init<C extends Record<string, new () => any>>(classMap: C): InstanceMap<C> {
  // your implementation
  return {} as any
}

class C1 { foo1() {} }
class C2 { foo2() {} }
const classMap = { C1, C2 };

const instances = init(classMap)
instances.C1.foo1()
instances.C2.foo2()

playground