TypeScript 泛型:'类型不可分配给类型 T'

Posted

技术标签:

【中文标题】TypeScript 泛型:\'类型不可分配给类型 T\'【英文标题】:TypeScript Generics: 'type is not assignable to type T'TypeScript 泛型:'类型不可分配给类型 T' 【发布时间】:2018-09-19 20:08:09 【问题描述】:

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

我认为下面显示的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 消息。

谢谢

【问题讨论】:

【参考方案1】:

如果你的函数总是返回一个Lion 它的结果类型不是真正的通用。例如,您可以编写 create&lt;Tiger&gt;(),而您的函数仍将返回 Lion。真正的泛型函数会返回一个遵循泛型参数的值。

正如你所发现的,你可以将构造函数作为参数传递:

function create<T>(c: new(): T; ): T 
    return new c();

或者你可以让你的函数不是通用的,并让它返回一个AnimalLion。如果您有基于确定返回类型的参数值的逻辑,则可以有更多的重载:

// 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

【讨论】:

感谢您的回复。对我来说是个坏例子。我的意思是可以根据开关选择返回的类。让我换个例子。 A true generic function would return a value that honors the generic parameter。所以现在我已经更改了我的示例并且在createInstance() 方法中有两个选项,我的类是否不是通用的,因为它总是需要返回一个扩展动物的类?我不希望它简单地返回一个 Animal,因为我可能想使用其他子类特定的方法和属性。相反,我只想知道返回的值 is 是一个 Animal,这样我就可以确定它有一个 makeSound() 方法,但我想要那个实际的子类实例。 @Joe 它仍然不是通用的,因为它不适用于任何T,仅适用于从Animal 派生的有限数量的类。您应该考虑重载选项,它正是您要寻找的,它根据参数值返回特定类型的动物。 谢谢提香。这很有帮助

以上是关于TypeScript 泛型:'类型不可分配给类型 T'的主要内容,如果未能解决你的问题,请参考以下文章

类型“字符串”不可分配给类型“WebkitAppearance |在 React + TypeScript 中未定义?

TypeScript 2.4.1 -> fontWeight -> 类型 'number' 不可分配给类型 '"inherit" | 400 |

react-router-dom TypeScript TS2322:类型'typeof Index'不可分配给类型

Mongoose TypeScript ObjectId 转换 - 类型“字符串”不可分配给类型“条件<ObjectId |未定义>'

Mongoose TypeScript ObjectId 转换 - 类型“字符串”不可分配给类型“条件<ObjectId |未定义>'

UserModel 不可分配给 Document | 类型的参数nulll [带有 Typescript 的猫鼬]