Можно ли использовать свойство 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[]