在 TypeScript 中使泛型参数的顺序变得多余?

Posted

技术标签:

【中文标题】在 TypeScript 中使泛型参数的顺序变得多余?【英文标题】:Make the order of generic arguments redundant in TypeScript? 【发布时间】:2022-01-03 12:16:49 【问题描述】:

我有一个中间件引擎,它使用与特定实现相关的各种通用参数键入。

export type Middleware<

  Store = never,
  Args = unknown,
  Response = unknown

> = (

  context: 
    endpoint: string
    args: Args
    locals: 
      store?: Store,
      [key: string]: unknown
    
  

) => Promise<Response|void>|Response|void

随着我使Middleware 的功能更加丰富,通用参数列表不断增加。有时 store 不会出现,而其他参数则存在。我知道我可以依赖默认值和参数顺序,但是(有更多参数在路上)这不是最好的开发人员体验,必须以正确的顺序列出参数并提供 unknownnever 给即将到来的参数在其他需要定义之前。

有没有更好的方法为不依赖顺序的泛型提供参数,这样我可能有任意数量的相关泛型参数,其余的默认为最一般情况下定义的东西?也许是某种地图?

【问题讨论】:

不。 javascript 没有命名参数! @jonrsharpe 您可以通过使用对象在 JavaScript 中有效地命名参数。所以你可以达到同样的目的。 TypeScript 中没有类似的 hack 吗?或者任何其他技巧来减少在泛型中传递冗余参数的需要? 有效但不是,你知道,实际上 我不确定拥有一个使用许多类型参数的 generic 是否是个好主意,其中一些参数可能相关,也可能不相关。在这种情况下听起来不是很“通用”。 也许你可以做一些事情,比如接受一个泛型类型参数,这是context结构的一个选项,但是,也许最好重新考虑这种方法。 有时过于通用的函数不是一个好主意 【参考方案1】:

您可以使用带有属性的单一类型:

type Get<T, K extends PropertyKey, TDefault> = 
    [T] extends [Record<K, infer U>] ? U: TDefault

export type Middleware<T extends 
  Store?: any,
  Args?: any,
  Response?: any
> = MiddlewareInternal<Get<T, 'Store', never>, Get<T, 'Args', unknown>, Get<T, 'Response', unknown>>
export type MiddlewareInternal<

  Store = never,
  Args = unknown,
  Response = unknown

> = (

  context: 
    endpoint: string
    args: Args
    locals: 
      store: Store,
      [key: string]: unknown
    
  

) => Promise<Response|void>|Response|void

Playground Link

它可能不是 100% 等效的,但它可能已经足够了。

【讨论】:

谢谢你;已经投票了,因为它在某种程度上允许我隐藏实现的复杂性。但我认为它的复杂性暗示了 cmets 中关于我的原始设计缺乏通用性的观点。我现在正在重新考虑如何构建我的泛型。 @shennan 我倾向于同意拥有大量通用参数是一个不好的迹象,所以你可能会考虑改变你的设计。

以上是关于在 TypeScript 中使泛型参数的顺序变得多余?的主要内容,如果未能解决你的问题,请参考以下文章

如何使泛型代理类型与静态类型检查器一起使用

TypeScript专题之泛型

选择Typescript的原因:支持定义执行时的泛型参数

如何避免在 Typescript 中分布多个泛型类型参数?

TypeScript 入门14.泛型

在 TypeScript 中,如何在具有多个类型参数的方法中推断出泛型类型参数?