использовать имя конструктора в качестве подписи индекса для типа возвращаемого значения - PullRequest
1 голос
/ 15 мая 2019

Можно ли использовать свойство 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[]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...