#javascript #typescript #generics #factory
#javascript #typescript #общие сведения #фабрика
Вопрос:
Доброе утро,
Проблема
я использую Typescript для создания приложения angular. Я хочу создать метод, который принимает аргумент типа и передает его на фабрику для создания нового экземпляра с использованием cTor. Это хорошо работает, если я знаю тип, но не если я этого не знаю. Например, это работает (строка 4):
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance<MdmCountry>(MdmCountry, x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance<T extends AbstractMdmStorable>(concrete: new(mdmObject: IMdmObject) => T, init: IMdmObject): T {
return new concrete(init);
}
Но это не работает, если я использую T вместо:
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance<T>(T, x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance<T extends AbstractMdmStorable>(concrete: new(mdmObject: IMdmObject) => T, init: IMdmObject): T {
return new concrete(init);
}
Я знаю о том факте, что Typescript переносит код в js и что T недоступен после этого процесса. Но есть ли способ создать универсальный экземпляр, который расширяет AbstractMdmStorable?
Примечания
- AbstractMdmStorable реализует IMdmObject
- MdmCountry расширяет AbstractMdmStorable
Ответ №1:
Его можно использовать T
как тип, но вы не можете использовать его как значение. Таким образом, вы не можете передавать T
здесь в качестве аргумента функции this.createInstance<T>(T, x))
.
Это можно решить с помощью внедрения зависимостей. Что вы хотите сделать, это передать класс (сам класс, а не экземпляр класса). Но вместо того, чтобы передавать его в качестве аргумента createInstance
функции, я бы рекомендовал сохранить класс как переменную экземпляра factory . В конструкторе вашей фабрики вы передаете класс, чтобы создать экземпляр фабрики для этого типа объекта.
Я не понимаю всех ваших типов здесь, но это будет выглядеть примерно так:
class MyFactory<T extends IMdmObject> {
constructor(private readonly concrete: new (mdmObject: IMdmObject) => T) {
}
list<T extends IMdmObject>(page = 1, pageSize = 50) {
this.http.get<T[]>(this.uri).pipe(tap(
_mdmObject => {
let _ = _mdmObject.map(x => this.createInstance(x));
this.mdmStoreController.dispatch(this.ressource, _mdmObject, StoreAction.MERGE);
}
)).subscribe();
}
createInstance(init: IMdmObject): T {
return new this.concrete(init);
}
}
Комментарии:
1. Привет, Линда, ты спасла мне день. Я совершенно новичок в универсальных функциях в ts, но я написал нечто подобное на c # несколько недель назад, поэтому я просто предполагал, что это работает одинаково в ts. После повторной проверки этого кода я обнаружил, что я использовал отражение там, чтобы захватить cTor. Хорошего дня.