[英]In TypeScript, how do I implement an interface with (a: type, b:type): any?
[英]In TypeScript, how do you express that a type T, declared inside an interface I, should be of whatever type U that will implement said interface I
我正在通过实现Fantasy Land Spec来探索 Typescript 类型系统,但在尝试实现Semigroup的规范时遇到了问题。
规范规定Semigroup
应遵守以下类型定义:
concat :: Semigroup a => a ~> a -> a
我理解这意味着实现Semigroup
的类型a
应该有一个concat
方法,该方法接受 a 类型a
参数并返回 a 类型a
参数。
我能想到在 TypeScript 中表达这种类型定义的唯一方法是:
interface Semigroup {
concat(other: this): this;
}
但是当我尝试在 class 上实现这个接口时,像这样:
class Sum implements Setoid, Semigroup {
constructor(readonly num: number) {}
concat(other: Sum): Sum {
return new Sum(this.num + other.num);
}
}
我收到一个编译器错误,告诉我:
Property 'concat' in type 'Sum' is not assignable to the same property in base type 'Semigroup'.
Type '(other: Sum) => Sum' is not assignable to type '(other: this) => this'.
Type 'Sum' is not assignable to type 'this'.
'Sum' is assignable to the constraint of type 'this', but 'this' could be instantiated with a different subtype of constraint 'Sum'.(2416)
感谢这个S/O 答案,我想我理解了这个问题。
我认为编译器本质上是在告诉我:您的界面说您应该采用具体类型的参数this
(在这种特殊情况下为Sum
),但是也可以传入扩展Sum
的 class 。
但是,我不知道如何解决它。 就是不知道Semigroup
中Semigroup的类型定义怎么表达。 如何表示在接口 I 中声明的类型 T 应该是实现所述接口 I 的任何类型 U?
这是 TS Playground 的链接。
我不想质疑您对幻想土地规范的解释,我承认我并不完全理解,所以我假设您的解释是正确的。
问题是您的class
可以扩展,所以this
可以指扩展的 class。 TypeScript 中没有final class
或等效项。
现在假设您有一个扩展Sum
的ExtendedSum
class 。 您的equals
实现仍然有效,因为(other: Sum) => boolean
可分配给(other: ExtendedSum) => boolean
。 实际上,将Sum
作为参数的 function 也可以采用ExtendedSum
(结构类型原则)。
但是,您的concat
实现不起作用,因为(other: Sum) => Sum
不能分配给(other: ExtendedSum) => ExtendedSum
。 实际上,返回Sum
的 function 不能分配给返回ExtendedSum
的 function ,因为Sum
不一定是ExtendedSum
。
您可以使用通用类型接口解决此问题:
interface Semigroup<T> {
concat(other: T): T;
}
class Sum implements Setoid, Semigroup<Sum> {
constructor(readonly num: number) {}
equals(other: Sum): boolean {
return this.num === other.num;
}
concat(other: Sum): Sum {
return new Sum(this.num + other.num);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.