TypeScript 中具有泛型类型参数的泛型类型的替代方案

Posted

技术标签:

【中文标题】TypeScript 中具有泛型类型参数的泛型类型的替代方案【英文标题】:Alternatives for a generic type with generic type parameters in TypeScript 【发布时间】:2021-06-11 10:28:23 【问题描述】:

假设我有两种类型的泛型函数,它们的返回类型不同。一个有返回类型T,另一个有T[]

type F1 = <T>(t: T) => T
type F2 = <T>(t: T) => T[]

我想知道如何将这两种类型合并为一种通用类型。我想这样做的方式是让新的泛型类型接受另一个泛型类型作为参数(如 C++ 的template template parameters):

// Caution, Fantasy-TypeScript ahead!

// Accepts generic type R as parameter
// to transform return type of generic function
type F<R> = <T>(t: T) => R<T>

// define F1 and F2 in terms of F
type Id<T> = T
type F1 = F<Id>
type F2 = F<Array>

但是,泛型泛型参数尚不受支持(2021 年 3 月)。请参阅TypeScript Issue 和related SO question 了解更多信息。

TypeScript 中的替代方案是什么?

【问题讨论】:

【参考方案1】:

一个简单的方法是使用Conditional Types:

type F<R> = <T>(t: T) => R extends void[] ? T[] : T

type F1 = F<void>   // <T>(t: T) => T
type F2 = F<void[]> // <T>(t: T) => T[]

使用Indexed Access Types可以实现更灵活的实现:

type R<T> =  Id: T, Array: T[] 
type F<K extends keyof R<any>> = <T>(t: T) => R<T>[K]

type F1 = F<'Id'>    // <T>(t: T) => T
type F2 = F<'Array'> // <T>(t: T) => T[]

请参阅my answer to a similar question,了解更多有关此技术的示例。

【讨论】:

以上是关于TypeScript 中具有泛型类型参数的泛型类型的替代方案的主要内容,如果未能解决你的问题,请参考以下文章

typescript :具有原始类型约束的泛型类型

是否可以在 TypeScript 中传播独特的泛型类型?

TypeScript 中每个键的泛型映射对象类型

Typescript 推断的泛型类型在条件类型中是未知的

TypeScript中的泛型

如何在流中定义具有指定类型的所有可选字段的泛型类型