gpt4 book ai didi

typescript - typescript 中的抽象泛型类

转载 作者:行者123 更新时间:2023-12-04 01:49:39 25 4
gpt4 key购买 nike

我在 typescript 中有一个抽象的泛型类,它有一个带有类类型变量参数的泛型方法。我尝试在派生类中实现抽象方法,发现 typescript 编译器不检查派生方法中的参数类型。

这是一个例子。我希望它在编译时失败 流程 上的方法1类因为参数类型错误。

难道我做错了什么?还是设计使然?或 typescript 编译器中的错误

class Product {
id: number;
name: string;
}

class Customer {
id: number;
name: string;
address: string;
}

export abstract class BaseClass<TParam> {
protected abstract process(param: TParam): void;
}

export class Class1 extends BaseClass<Customer> {
protected process(param: Product): void {
console.log(param);
}
}

最佳答案

该行为不是错误。

TypeScript 使用 structural类型系统,因此如果两个对象类型具有兼容的属性,则它们是兼容的,即使类型具有不同的名称或来自不同的命名类/接口(interface)。

那么请注意,Customer可分配给 Product , 因为每 Customer有一个 number值(value)id属性(property)和 string值(value)name属性(property)。反过来是不正确的。 Product不能分配给 Customer , 因为不是每个 Product有必要的address属性(property)。

这是一个错误吗?编译器认为 Customer 是您的代码的问题吗?是一种特殊的Product ?如果是,最简单的解决方法是为每种类型添加一个属性,编译器可以使用它来区分它们。例如:

class Product {
id!: number;
name!: string;
type?: "product"
}

class Customer {
id!: number;
name!: string;
address!: string;
type?: "customer"
}

现在代码会根据需要给你一个错误:
export abstract class BaseClass<TParam> {
protected abstract process(param: TParam): void;
}

export class Class1 extends BaseClass<Customer> {
protected process(param: Product): void { // error!
// ~~~~~~~ <-- Type 'Customer' is not assignable to type 'Product'.
console.log(param);
}
}

或者编译器认为 Customer 可能很好。是一种特殊的 Product .在这种情况下,您可以不理会您的类型,我们可以检查原因 process()不会导致编译器错误:
export class Class1 extends BaseClass<Customer> {
protected process(param: Product): void { // no error
console.log(param);
}
}

在这种情况下, BaseClass<Customer>应该有 process()接受 Customer 的方法.但是这个 process()接受更宽的类型 Product反而。可以吗?是的!因为如果 process()接受任何 Product参数,那么它肯定接受任何 Customer论点(因为 Customer 是一种特殊的 Product ,因此 Class1 正确扩展了 BaseClass<Customer> )。这是一个演示方法参数如何 contravariant ;允许子类方法接受比父类(super class)型上的相同方法更广泛的参数。 TypeScript 确实允许方法参数是逆变的,因此没有错误。

方法参数为 covariant 是不安全的(其中子类方法接受比它们各自的父类(super class)方法更具体的参数类型),但是包括 TypeScript 在内的一些语言允许它表示一些常见的用例。也就是说,TypeScript 允许方法参数既是逆变的又是协变的,也称为 bivariant ,尽管它缺乏类型安全性。因此,如果您以另一种方式进行操作,也不会出现错误:
export class Class2 extends BaseClass<Product> {
protected process(param: Customer): void { // no error, bivariant
console.log(param);
}
}

回顾一下:您可以将属性添加到 CustomerProduct使它们在结构上不相关,或者您可以不理会它们, Class1.process()将编译没有错误。无论哪种方式,编译器都按预期运行。

希望有帮助。祝你好运!

关于typescript - typescript 中的抽象泛型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53843170/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com