使用构造函数名称作为返回类型的索引签名

时间:2019-05-15 09:40:49

标签: typescript generics angular7

是否可以将构造函数的name属性用作索引签名,而分别用作属性名称?

示例

我想具有用于服务器响应的通用映射功能。这些可以包括多个实体。 例如

const serverResponse = {
    User: {...},
    UserGroup: {...},
    ...someServerResponseStuff...
}

希望的结果:

const mappedResponse: {User: User, UserGroup: UserGroup} = mapToEntity(serverResponse, User, UserGroup);

获得的结果:

const mappedResponse: {[key: string]: User | UserGroup} = mapToEntity(serverResponse, User, UserGroup);

当前mapToEntity实现

type ConstructorFunction<T> = new(...args: any[]) => T;

为了更好的可读性,只有两个指定的构造函数函数参数。在实际的实施中,Threre会更多。

export function mapToEntity<A>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>): A[];
export function mapToEntity<A, B>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>, cFn2: ConstructorFunction<B>): {[key: string]: A[] | B[]}; // specify index signatures here
export function mapToEntity<A, B>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>, cFn2?: ConstructorFunction<B>, ...constructorFunctions: ConstructorFunction<any>[]): A[] | {[key: string]: any[]} {

  let cArray: ConstructorFunction<any>[] = [cFn1];

  if(cFn2) {
    cArray.push(cFn2);
  }

  cArray = [...cArray, ...constructorFunctions];

  if (cArray.length > 1) {
    const result: {[key: string]: any[]} = {};
    for (const constructorFunction of cArray) {
      const modelName: string = constructorFunction.name;
      result[modelName] = new constructorFunction(serverResponse[modelName]);
    }
    return result;
  } 

  const x = new cFn1(serverResponse[modelName]);
  return x; 
}

第二重载的错误定义

export function mapToEntity<A, B>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>, cFn2: ConstructorFunction<B>): {cFn1.name: A[], cFn2.name: B[]}; // specify index signatures here

或更可能

export function mapToEntity<A, B>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>, cFn2: ConstructorFunction<B>): {ConstructorName<cFn1<A>>: A[], ConstructorName<cFn2<B>>: B[]}; // specify index signatures here

编辑

到目前为止,我得到的最好的结果是使用对象析构函数重命名了结果。 但这还远非理想

export function mapToEntity<A, B>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>, cFn2: ConstructorFunction<B>): {entity1: A[], entity2: B[]};
const { 'entity1': user, 'entity2': userGroup } = mapToEntity(fakeResponse, User, UserGroup);

Edit2

我找到了解决方案,我可以忍受

export function mapToEntity<A, B>(serverResponse: IServerResponse, cFn1: ConstructorFunction<A>, cFn2: ConstructorFunction<B>): [A[], B[]];
const [user, userGroup] = mapToEntity(fakeResponse, User, UserGroup);

您还可以将其保存在一个变量中,并从数组中获取类型安全的属性

    const test: [User[], UserGroup[]] = mapToEntity(fakeResponse, User, UserGroup);
    const x = test[1]; // has type UserGroup[]

0 个答案:

没有答案