【问题标题】:How to explicitly define the return type of a generic returned class in TypeScript?如何在 TypeScript 中显式定义泛型返回类的返回类型?
【发布时间】:2018-12-20 05:55:50
【问题描述】:

我有这样的代码:

import * as events from 'events' // Node.js events module

// my own version of EventEmitter with better typing
interface IEventEmitter<EventTypes> { /* ... */ }

// eslint-disable-next-line typescript/explicit-function-return-type
export function EventEmitter<EventTypes>() {
  // merge the IEventEmitter interface and EventEmitter as IEventEmitter
  // implementation into one.
  // XXX Is there a better way?
  return class NewEventEmitter
    extends ((events.EventEmitter as unknown) as IEventEmitter<EventTypes>)
    implements IEventEmitter<EventTypes> {}
}

如你所见,我禁用了一个 eslint 规则,这样它就不会抱怨我没有指定返回类型,而是让返回类型被推断出来。

但是,我将如何编写返回类型?

编辑:这是一个playground example,显示@KarolMajewski 的答案对我不起作用。上面写着Cannot find name 'NewEventEmitter'. Did you mean 'NodeEventEmitter'?

编辑 2:@KarolMajewski 的回答确实有效。要使其工作,必须将类分配给局部变量。这是playground example

【问题讨论】:

  • 使用IntelliSense查看推断类型,然后手动复制到返回类型注解? (安装了 node.js 事件的人可能会更明确地告诉你)
  • @jcalz 如果这行得通,那就太棒了。智能感知告诉我要做到这一点,这实际上导致了 Karol Majewski 在那个答案中告诉我要做的事情,并且我用游乐场链接更新了问题,表明这不起作用。
  • 哦,我明白了,它使用的是内部作用域中的某个名称。

标签: typescript generics


【解决方案1】:

在编写显式返回类型和让 TypeScript 推断其类型之间,还有第三种方法:

import * as events from 'events';

interface IEventEmitter<EventTypes> { /* ... */ }

export function EventEmitter<EventTypes>(): typeof MyClass {
  const MyClass = class extends events.EventEmitter implements IEventEmitter<EventTypes> {};

  return MyClass;
}

虽然这有点小技巧,但它需要一个所谓的不必要的局部变量。在这种情况下,此变量 (MyClass) 仅用于从中读取类型。

【讨论】:

  • 我希望这能奏效。查看我添加到问题中的操场示例,以表明它不起作用。它说Cannot find name 'NewEventEmitter'. Did you mean 'NodeEventEmitter'?
  • 这看起来对我有用。您的操场示例未按照此答案的建议使用 const NewEventEmitter = class extends 语法。修复它,它应该可以工作。
  • @jcalz 是正确的——您忘记在返回之前将 NewEventEmitter 分配给局部变量。应该是const NewEventEmitter = class extends /* ... */,然后是return NewEventEmitter;
  • 你说得对,这行得通!为我的问题添加了游乐场链接。但是,内部范围如何看起来似乎是外部的,这是没有意义的。换句话说,我会认为返回类型只能从外部范围内的类型中指定。
  • 我无法让它在一个使用 TypeScript 3.3.0-dev.20181129 的项目中工作。我从添加到上述问题的工作示例中复制了确切的代码,但在typeof NewEventEmitter 上它抱怨“导出函数的返回类型具有或正在使用私有名称'NewEventEmitter'”。有任何想法吗?我正在生成声明文件。也许它遇到了以下问题? github.com/Microsoft/TypeScript/issues/6307
【解决方案2】:

声明返回类型为IEventEmitter&lt;EventTypes&gt;

function makeEventEmitterClass<EventTypes>(): IEventEmitter<EventTypes> {
  // merge the IEventEmitter interface and EventEmitter as IEventEmitter
  // implementation into one.
  return class NewEventEmitter
    extends ((NodeEventEmitter as unknown) as IEventEmitter<EventTypes>)
    implements IEventEmitter<EventTypes> {}
}

【讨论】:

  • 我也这么认为,但它破坏了声明导出/导入的工作方式。
猜你喜欢
  • 1970-01-01
  • 2022-10-12
  • 2021-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 1970-01-01
  • 2019-09-06
相关资源
最近更新 更多