Typescript泛型约束对类的示例不起作用?

6ie5vjzr  于 2022-12-19  发布在  TypeScript
关注(0)|答案(2)|浏览(162)

我有一个父类 A,一个 A 的子类 B,以及一个 B 的子类 C

class A {}
class B extends A {}
class C extends B {}

我想创建一个泛型函数 f,它的唯一参数是对扩展 B 的类的示例的约束。
在我对typescript的理解中,函数应该如下所示:

function f<T extends B>(p: T): any {}

然而,当我把A或任何其他类型(数字、字符串等)的示例作为参数传递时,ts类型检查器并不抱怨。

const a = f(new A()); // should complain
const b = f(new B());
const c = f(new C());
const d = f(123); // should complain

我是不是漏掉了什么明显的东西?是不是类型检查器的配置问题?

aoyhnmkz

aoyhnmkz1#

Typescript有结构类型。编译器检查的是结构,而不是实际(名义)类型。
由于类型是空的(没有成员),满足它们的类型比预期的要多得多。
但是,向类型中添加成员(例如,向B添加A中不存在的成员),以便编译器可以检查结构,并检查约束,正如您所期望的那样

class A {
  a!: string;
}
class B extends A {
  b!: string;
}
class C extends B {}

function f<T extends B>(p: T): any {}

const a = f(new A()); // complains
const b = f(new B());
const c = f(new C());
const d = f(123); // complains
tkclm6bt

tkclm6bt2#

你不需要泛型。泛型是用来从你的泛型类型中创建不同类型的函数。这里你只需要寻找一个特定类型的函数,它只接受B的示例。
此外,你最好在类中定义一些属性,否则所有空类示例都将被赋值给空类示例。This github issue有更多信息。原因似乎是结构类型系统。
结构化类型系统(或基于属性的类型系统)是类型系统的主要类别,其中类型兼容性和等价性由类型的实际结构或定义确定,而不是由诸如名称或声明位置之类的其他特征确定。
这里是this的wiki
你可以看看这个来理解:

class A {
      private a: number
}
class B extends A {
    private b: number
}
class C extends B {
    private c: number
}

function f(x : B): any {

}

const a = f(new A()); // should complain
const b = f(new B());
const c = f(new C());
const d = f(123); // should complain

连结(请忽略Playground内的禁止使用警告,与问题无关)
请注意,如果从类中删除属性,错误将消失。
PS:你仍然可以在这里使用泛型,比如:

class A {
      private a: number
}
class B extends A {
    private b: number
}
class C extends B {
    private c: number
}

function f<P extends B>(x : P): any {

}

const a = f(new A()); // should complain
const b = f(new B());
const c = f(new C());
const d = f(123); // should complain

链接

相关问题