TypeScript泛型:“类型不可分配给类型T”

Joe*_*Joe 6 typescript typescript-generics

我已经建立了一个工厂,它将创建某些类的实例。我想使用泛型来确保返回的所有对象均来自扩展抽象类的子类。

我认为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();
Run Code Online (Sandbox Code Playgroud)

我在TypeScript泛型文档的末尾读到:

使用泛型在TypeScript中创建工厂时,有必要通过其构造函数来引用类类型。例如,

function create<T>(c: {new(): T; }): T {
    return new c();
}
Run Code Online (Sandbox Code Playgroud)

但是我真的不想在可能的情况下将类构造函数传递给函数,并且想了解为什么我not assignable to type T首先得到消息。

谢谢

Tit*_*mir 4

如果你的函数总是返回 a ,那么Lion它的结果类型并不是真正通用的。例如,您可以编写create<Tiger>(),并且您的函数仍然会返回一个Lion. 真正的泛型函数将返回一个遵循泛型参数的值。

正如您发现的那样,您可以将构造函数作为参数传递:

function create<T>(c: {new(): T; }): T {
    return new c();
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使您的函数不是通用的,并让它返回一个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
Run Code Online (Sandbox Code Playgroud)