首页 > 解决方案 > 使用构造函数名称作为返回类型的索引签名

问题描述

是否可以将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;

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

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);

编辑2

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

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[]

标签: typescriptgenericsangular7

解决方案


推荐阅读