Typeof类不能分配给类

时间:2018-10-26 10:04:15

标签: typescript typescript-typings

这是一些示例代码,我无法弄清楚为什么它会引发错误。 在同一方面的任何帮助将不胜感激。 我试图在getClass函数中创建一个类实例,但是打字稿抛出了一些错误。 该代码在javascript中运行,但是我找不到解决打字稿错误的方法。

这是说“类型'typeof Ab'无法分配给类型'Ab'。   类型“ Ab”的类型中缺少属性“ b”。

class A {
    public a: string
    constructor(args: Partial<A>) {
        this.a = args.a;
    }
};

class Ab extends A {
    public b: string
    constructor(args: Partial<Ab>) {
        super(args);
        this.b = args.b;
    }
};

class Ac extends A {
    public c: string
    constructor(args: Partial<Ac>) {
        super(args);
        this.c = args.c;
    }
};

const enumMap = {
    ab: 1 as 1,
    ac: 2 as 2,
};

type enumMap = typeof enumMap[keyof typeof enumMap];

type enumClass<T extends enumMap> =
    T extends typeof enumMap.ab ? Ab :
    T extends typeof enumMap.ac ? Ac : never;

const enumClassMap: { [K in enumMap]: enumClass<K> } = {
    [enumMap.ab]: Ab, //Error
    [enumMap.ac]: Ac, //Error
}

function getClass<T extends enumMap>(type: T) {
    let abc: { new(): enumClass<T> } = enumClassMap[type];
    return new abc({});
};

getClass(enumMap.ac);

1 个答案:

答案 0 :(得分:2)

问题在于enumClassMap需要一个Ab和Ac类的对象:

const enumClassMap: { [K in enumMap]: enumClass<K> } = {
    [enumMap.ab]: new Ab({a: "a", b: "b"}), //Error
    [enumMap.ac]: new Ac({a: "a", c: "c"}), //Error
}

我认为这应该是解决您问题的正确方法:

type enumClass<T extends enumMap> = T extends typeof enumMap.ab ? typeof Ab 
    : T extends typeof enumMap.ac ? typeof Ac : never;

function getClass<T extends enumMap>(type: T) {
  let abc: (new (args: any) => Ab | Ac) = enumClassMap[type];
  return new abc({a: "a"});
};

更新:

这将是键入示例的另一个示例。但我不知道为什么需要演员。索引类型的类型推断似乎存在一些问题。

class A {
  public a: string;
  constructor(args: Partial<A>) {
    this.a = args.a;
  }
}

class Ab extends A {
  public b: string;
  constructor(args: Partial<Ab>) {
    super(args);
    this.b = args.b;
  }
}

class Ac extends A {
  public c: string;
  constructor(args: Partial<Ac>) {
    super(args);
    this.c = args.c;
  }
}

enum enumMap {
  Ab = 1,
  Ac
}

type enumClass<T extends enumMap> = T extends typeof enumMap.Ab
  ? Ab
  : T extends typeof enumMap.Ac ? Ac : never;

interface ConstructorOf<T extends enumMap> {
  new (args: any): enumClass<T>;
}

const enumClassMap: { [T in enumMap]: ConstructorOf<T> } = {
  [enumMap.Ab]: Ab,
  [enumMap.Ac]: Ac
};

function getClass<T extends enumMap>(type: T) {
  return new enumClassMap[type]({a: "a"}) as enumClass<T>;
}

getClass(enumMap.Ac);