简体   繁体   中英

Alternatives for a generic type with generic type parameters in TypeScript

Suppose I have two types for generic functions that only differ in their return type. One has return type T , the other T[] :

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

I wondered how those two types could be consolidated into one generic type. The way I imagined doing that was to have that new generic type accept another generic type as a parameter (like C++'s 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>

However, generic generic parameters are not supported yet (March 2021). See TypeScript Issue and a related SO question for more information.

What would be an alternative in TypeScript?

A simple approach would be to use 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[]

A more flexible implementation can be achieved using 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[]

See my answer to a similar question for a more involved example of this technique.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM