Например, есть два класса
class Animal {
async getEntity() {
return await Promise.resolve('There is a string')
}
async specificAnimalMethod() {
return await Promise.resolve('Animal Promise resolved')
}
}
class Human {
async getEntity() {
return await Promise.resolve(777)
}
async specificHumanMethod() {
return await Promise.resolve('Human Promise resolved')
}
}
Иногда нужно создать экземпляр одного класса, иногда - другого. И дальше работать с методами этого экземпляра. Эти методы иногда пересекаются, иногда уникальны для каждого класса. Те, что пересекаются, могут возвращать одинаковый тип данных, а могут - разные типы. Заведомо я не знаю, экземпляр какого класса нужно создать. И могу ориентироваться только на строку в пропсах, которые прилетают с бэка:
{ instance: 'animal' }
// либо
{ instance: 'human' }
Если прилетел animal - то нужно инстанцироваться от Animal, если human - то от Human.
Самое очевидное, что приходит в голову - это написать словарь классов и по ключу выдергивать из него нужный:
const dict = {
animal: Animal,
human: Human
};
const get = (key: keyof typeof dict) => {
return dict[key];
};
const TargetClass = get(props.instance); // Допустим props.instance === 'animal'
const instance = new TargetClass();
И в обычном JS такая история бы прокатила, но в случае с TS - у меня как бы нет доступа к непересекающимся методам. Например, инстанцировавшись от Animal, я не могу вызвать его метод specificAnimalMethod, потому что
Property 'specificAnimalMethod' does not exist on type 'Animal | Human'. Property 'specificAnimalMethod' does not exist on type 'Human'
Что вполне ожидаемо, т.к. возвращаемый тип этого геттера: typeof Animal | typeof Human
А также я не знаю точный тип, который вернет метод getEntity, который есть у обоих классов, но возвращающий разные типы. И по факту вообще в моем случае возвращаемым типом окажется any.
instance.getEntity().then((res) => console.log(res)) // (parameter) res: any
Как можно решить такую проблему? Полагаю, что можно было бы чего-нибудь наколдовать с использованием InstanceType, но не могу сообразить, как.