我创建了一个工厂,可以创建某些类的实例。我想使用泛型来确保返回的所有对象都来自扩展抽象类的子类。
我认为下面显示的createInstance
方法的逻辑可以描述为'createInstance()将返回一个类型T
,它被约束为一个扩展Animal的类。
如您所见,Lion扩展了Animal,但我仍然收到编译器警告type Lion is not assignable to type T
。
abstract class Animal {
abstract makeSound(): void;
}
class Bear extends Animal {
public makeSound() {
console.log('growl');
}
}
class Lion extends Animal {
public makeSound() {
console.log('roar');
}
}
function createInstance<T extends Animal>(type: string): T {
switch(type) {
case 'bear':
return new Bear(); // 'type Bear is not assignable to type T'
case 'lion':
return new Lion(); // 'type Lion is not assignable to type T'
}
}
createInstance().makeSound();
我已在TypeScript Generics文档末尾阅读:
使用泛型在TypeScript中创建工厂时,这是必要的 通过构造函数引用类类型。例如,
function create<T>(c: {new(): T; }): T { return new c(); }
但我真的不想在可能的情况下将类构造函数传递给函数,并且想要理解为什么我首先得到not assignable to type T
消息。
由于
答案 0 :(得分:2)
如果您的函数始终返回Lion
,那么它的结果类型并不是通用的。例如,你可以写create<Tiger>()
,你的函数仍会返回Lion
。真正的泛型函数将返回一个值来支持泛型参数。
您可以将构造函数作为参数传递,如您所发现的那样:
function create<T>(c: {new(): T; }): T {
return new c();
}
或者您可以使您的功能不是通用的,并让它返回Animal
或Lion
。如果您具有基于确定返回类型的参数值的逻辑,则可能会有更多重载:
// Public signatures, we tie function parameter values to return value for specific types
function createInstance(type: "Lion"): Lion
function createInstance(type: "Tiger"): Tiger
// Private signature, not visible from outside
function createInstance(type: "Lion" | "Tiger"): Animal {
if(type === "Lion") {
return new Lion();
}
else if(type === "Tiger") {
return new Tiger();
}
}
let tiger = createInstance("Tiger"); // will be typed as Tiger
let lion = createInstance("Lion");// will be typed as Lion
let err = createInstance("Lama");// will be an error since the function does not know how to create a Lama