Typescript 类型脚本、不可变记录、泛型和;类型集合

Typescript 类型脚本、不可变记录、泛型和;类型集合,typescript,immutable.js,Typescript,Immutable.js,版本: 打字稿2.8 不可变:4.0 RC.9 我试图创建一组模型类,每个类都有一些共同的属性。现在,我想创建一个函数,该函数将使用从任何模型获取实例的泛型类型输入对公共属性进行操作 一个简单(且有效)的版本: 我遇到的问题是TS抛出的错误,请参阅上面的内联注释了解错误。如果你知道如何解决它或如何做不同的,请让我知道 import { Set, Record } from 'immutable'; class Factory {} class AnimalFactory extends

版本:

  • 打字稿2.8
  • 不可变:4.0 RC.9
我试图创建一组模型类,每个类都有一些共同的属性。现在,我想创建一个函数,该函数将使用从任何模型获取实例的泛型类型输入对公共属性进行操作

一个简单(且有效)的版本:

我遇到的问题是TS抛出的错误,请参阅上面的内联注释了解错误。如果你知道如何解决它或如何做不同的,请让我知道

import { Set, Record } from 'immutable';


class Factory {}
class AnimalFactory extends Factory {
  public static x: Set<{ id: string }> = Set([]);
}
class BeastFactory extends Factory {
  public static x: Set<{ id: string }> = Set([]);
}

function getEntityId<T extends keyof TypeMap>(entity: T) {
  const factory = TypeMap[entity];
  factory.x.add({ id: 'id' })
}

type TypeMap = typeof TypeMap;
const TypeMap = {
  a: AnimalFactory,
  b: BeastFactory,
}
const animal2Defaults = {
  foo: '',
  x: Set<keyof IAnimalAttributes>([]),
};
export interface IAnimalAttributes {
  foo?: string;
  x?: Set<keyof IAnimalAttributes>;
}

class AnimalFactory2 extends Record<Required<IAnimalAttributes>>(animal2Defaults) {
  public constructor(config: IAnimalAttributes) { super(config); }
}


const beast2Defaults = {
  bar: '',
  x: Set<keyof IBeastAttributes>([]),
};
interface IBeastAttributes {
  bar?: string;
  x?: Set<keyof IBeastAttributes>;
}

class BeastFactory2 extends Record<Required<IBeastAttributes>>(beast2Defaults) {
  public constructor(config: IBeastAttributes) { super(config); }
}

function getEntityId2<T extends keyof TypeMap2>(entity: T, record: TypeMap2[T]) {
  record.x.add('x'); // [ts] Cannot invoke an expression whose type lacks a 
  // call signature. Type '((value: "foo" | "x") => Set<"foo" | "x">) | 
  // ((value: "x" | "bar") => Set<"x" | "bar">)' has no compatible call signatures.

  const unionRecord: TypeMapUnion = record;
  unionRecord.x.add('x'); // [ts] Cannot invoke an expression whose type lacks a call signature. 
  // Type '((value: "foo" | "x") => Set<"foo" | "x">) | ((value: "x" | "bar") => Set<"x" | "bar">)' has no 
  // compatible call signatures.
  // (property) add: ((value: "foo" | "x") => Set<"foo" | "x">) | ((value: "x" | "bar") => Set<"x" | "bar">)

  const injectRecord: AttributeUnionRecords = record; // [ts]
  // Type 'TypeMap2[T]' is not assignable to type 'AttributeUnionRecords'.
  //   Type 'AnimalFactory2 | BeastFactory2' is not assignable to type 'AttributeUnionRecords'.
  //     Type 'AnimalFactory2' is not assignable to type 'AttributeUnionRecords'.
  //       Type 'AnimalFactory2' is not assignable to type 'Record<Required<IAnimalAttributes> | Required<IBeastAttributes>> & Readonly<Required<IBeastAttrib...'.

  if (record instanceof BeastFactory2) {
    record.x.add('x')
  }
}

function createInstance<T extends keyof TypeMap>(entity: T) {
  const instance = new TypeMap2[entity]({}); // [ts] Cannot use 'new' with an expression whose type lacks a call or construct signature.
  // (parameter) entity: T extends "a" | "b"
  instance.x.add('x')
}
type AttributeUnion2 = Required<IBeastAttributes>;
type AttributeUnionRecords = Record<Required<IAnimalAttributes> | Required<IBeastAttributes>>
  & Readonly<Required<IAnimalAttributes> | Required<IBeastAttributes>>;
type TypeMapUnion = AnimalFactory2 | BeastFactory2;
type TypeMap2 = {
  a: AnimalFactory2,
  b: BeastFactory2,
};
const TypeMap2 = {
  a: AnimalFactory2,
  b: BeastFactory2,
}