【问题标题】:TypeScript infer second argument of a function first argumentTypeScript 推断函数第一个参数的第二个参数
【发布时间】:2021-12-20 09:11:44
【问题描述】:

是否可以从另一个参数推断出一个函数参数?我想根据第一个参数的推断来推断第二个参数。

当前代码可以在 GitHub slickEventHandler.interface.ts 上,如下

export type GetSlickEventType<T> =
  T extends (infer U)[] ? U :
  T extends (...args: any[]) => infer U ? U :
  T extends SlickEvent<infer U> ? U : T;

export type GetEventType<T> = T extends infer U ? U : T;

type Handler<H> = (e: SlickEventData, data: GetSlickEventType<H>) => void;

export interface SlickEventHandler<T = any> {
  subscribe: (slickEvent: SlickEvent<T>, handler: Handler<T>) => SlickEventHandler<T>;
  unsubscribe: (slickEvent: SlickEvent<T>, handler: Handler<T>) => SlickEventHandler<T>;
  unsubscribeAll: () => SlickEventHandler<T>;
}

这使我可以执行以下操作(实时代码here

const onSelectedRowsChangedHandler = this._grid.onSelectedRowsChanged;
(this._eventHandler as SlickEventHandler<GetSlickEventType<typeof onSelectedRowsChangedHandler>>).subscribe(onSelectedRowsChangedHandler, (_e, args) => {
  args.column;
});

这可以进行正确的推断

但是,我正在寻找的是一种更简单的方法,如下所示(但我目前使用下面的代码得到的是 args 被推断为 any

this._eventHandler.subscribe(onHeaderCellRenderedHandler, (_e, args) => {
  const column = args.column;
  const node = args.node;
});

因此,正如我在问题中提到的那样,为了使其起作用,我需要推断第一个参数并以某种方式创建一个可供第二个参数使用的别名。最新版本的 TypeScript 可以做到吗?

【问题讨论】:

  • 请提供可重现的例子

标签: typescript typescript-generics typescript3.0


【解决方案1】:

我认为您希望方法是通用的而不是接口,因此您会将通用放在函数定义而不是接口名称中。

export interface SlickEventHandler {
  subscribe: <T>(slickEvent: SlickEvent<T>, handler: Handler<T>) => this;
  unsubscribe: <T>(slickEvent: SlickEvent<T>, handler: Handler<T>) => this;
  unsubscribeAll: () => this;
}

那么当你调用方法时会推断出泛型。

【讨论】:

  • 是的,这有点好,但这仍然不是我正在寻找的简短语法,我仍然需要输入两次事件(或使用仍然计为 2 的变量)。 this._eventHandler.subscribe&lt;GetSlickEventType&lt;typeof this.grid.onScroll&gt;&gt;(this.grid.onScroll, (e, args) =&gt; { /* ...*/ }); 顺便说一句,在您的演示中,它不能再返回 &lt;T&gt;,因为您将它从泛型中删除,所以它应该简单地返回 SlickEventHandler,我同意 unsubscribeAll 应该什么都不返回。我的问题仍然存在,是否可以从第一个论点推断 fn 第二个论点?
  • 不指定泛型不起作用?就像 try this._eventHandler.subscribe(this.grid.onScroll, (e, args) =&gt; { /* ...*/ }); 它应该根据输入参数解析泛型。此外,我不确定您所说的“在您的演示中,它不能返回 &lt;T&gt;,因为您已从通用中删除它”我将其从 unsubscribeAll 中删除,但它对其他 2 仍然有效。
  • 哦,哇,你说得对,我没有意识到它实际上是在做一个完整的推理,亲爱的!!!至于&lt;T&gt;,我的意思是新输出必须是SlickEventHandler 而不是SlickEventHandler&lt;T&gt;,因为&lt;T&gt; 不再作为接口的泛型提供(之前它是interface SlickEventHandler&lt;T = any&gt; { },现在是interface SlickEventHandler { },换句话说,它应该是这个subscribe: &lt;T = any&gt;(slickEvent: SlickEvent&lt;T&gt;, handler: Handler&lt;T&gt;) =&gt; SlickEventHandler;(只需删除&lt;T&gt; 表单输出。SlickEventHandler 是可管道的,这就是它返回自身的原因
  • 哦,我错过了它正在返回本身(你有很多类似命名的类型),在这种情况下你不应该只是返回 this 类型吗?
  • 是的,为旧的 JS 库添加 TS 接口有时也会令人困惑,我有时对要使用的接口名称没有想法。添加this 作为返回类型是另一个好主意,我什至不知道我们可以在接口中使用this。感谢所有伟大的建议,通过适当的推理,它使我的代码更易于使用。
猜你喜欢
  • 2019-01-22
  • 2020-09-24
  • 1970-01-01
  • 2019-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-13
  • 2018-03-22
相关资源
最近更新 更多