【问题标题】:Typescript - Why implementation of the interface is not forced accordinglyTypescript - 为什么没有相应地强制实现接口
【发布时间】:2020-07-30 19:44:47
【问题描述】:

我想知道为什么实现两次相同的泛型接口但使用不同的参数并不能在派生类中强制执行正确的签名。泛型参数的类型被省略。

请看样例:

interface IEvent { id: number; }
interface IHandle<T> {
  handle(event: T): void;
}

class EmailSentEvent implements IEvent {
  constructor(public id: number, public address: string) {}
}

class UserRegisteredEvent implements IEvent {
  constructor(public id: number) {}
}

class MailHandlerState implements 
  IHandle<EmailSentEvent>, 
  IHandle<UserRegisteredEvent> 
{
  // One implementation is enough to satisfy both interfaces
  handle = (event: EmailSentEvent): void => {

  };
}

Sandbox

有没有办法强制执行这两个泛型参数?谢谢!

【问题讨论】:

  • 似乎是 TypeScript 编译器中的一个错误。我相信它应该要求handle 输入(event: EmailSentEvent | UserRegisteredEvent): void
  • 看起来问题更大,并且在检查对象道具的类型兼容性时没有应用严格的函数类型。 const h: IHandle&lt;UserRegisteredEvent&gt; = { handle(e: EmailSentEvent) { e.address.toString() } }; 将在运行时爆炸。 Playground
  • 这很奇怪,但是在界面中更改为handle: (event: T) =&gt; void; 可以按预期工作。 Try
  • @AlekseyL。非常好的观察!

标签: typescript typescript-generics


【解决方案1】:

TLDR:

要完成这项工作,请更改方法符号

interface IHandle<T> {
    handle(event: T): void;
}

具有函数类型的属性

interface IHandle<T> {
    handle: (event: T) => void;
}

Playground

** 在这种特定情况下,实现仍然可以使用方法语法


事实证明这是按预期工作的:

--strictFunctionTypes 模式,在该模式下,函数类型参数位置以逆变方式而不是双变量方式进行检查。更严格的检查适用于所有函数类型,源自方法或构造函数声明的函数类型除外。专门排除方法以确保泛型类和接口(例如 Array)继续主要以协变方式相关。严格检查方法的影响将是一个更大的突破性变化,因为大量泛型类型将变得不变(即便如此,我们可能会继续探索这种更严格的模式)

Source

同样在handbook

【讨论】:

  • 有趣!即使您以这种方式声明它,也不必以这种方式实现,您可以在类中使用方法语法。不错!
  • 哇,里面嵌入了一些有趣的细节!
  • 该死的感觉很糟糕,它强制执行一个包罗万象的函数(event: EmailSentEvent | UserRegisteredEvent),它必须进行模式匹配才能实现function per typeof T。但我很高兴编译器至少强制采用某种类型安全的方式来做到这一点:))。我猜编译器可能很聪明,并在将其转换为普通 JS 时映射到字典 > 中,同时仍允许多个具有相同名称的方法/属性函数。非常感谢@T.J.Crowder
  • @CristianE。这是打字稿中的常规重载语法。制作智能地图并非易事,因为类型不会进入运行时(在编译时擦除)
猜你喜欢
  • 1970-01-01
  • 2017-05-14
  • 2016-11-30
  • 1970-01-01
  • 2021-01-14
  • 2017-08-07
  • 2023-03-16
  • 2015-05-08
  • 1970-01-01
相关资源
最近更新 更多