Typescript вывести дженерики в дженерики - PullRequest
1 голос
/ 11 апреля 2020

Проблема

Допустим, у меня есть интерфейс Wrapped:

interface Wrapped<T> {
  data: T
}

И я хочу определить функцию следующим образом:

function f<T>(arg: any): T {
  const obj: Wrapped<T> = doSomethingAndGetWrappedObject<T>(arg)
  return obj.data
}

// Don't pay attention to the argument, it is not important for the question
const n: number = f<number>(/* ... */)

Проблема в моем приложении очень неудобно передавать number в качестве аргумента типа, я хотел бы вместо этого передать Wrapped<number>, т.е. вызвать f следующим образом:

const n: number = f<Wrapped<number>>(/* ... */)

Вопрос: как набрать f, чтобы сделать это возможным?

Что я пробовал

function f<T extends Wrapped<V>, V>(arg: any) {
  // ...
}
// Now this works, but it is very annoying to write the second type argument
const n: number = f<Wrapped<number>, number>() 
// I would like to do this, but it produces an error
// Typescript accepts either no type arguments or all of them
const n: number = f<Wrapped<number>>()
// This just works in an unpredictable way
function f<T extends Wrapped<any>>(
  arg: any
): T extends Wrapped<infer V> ? V : any {
  /* ... */
}

1 Ответ

2 голосов
/ 11 апреля 2020

Вы можете создать вспомогательный тип для извлечения обобщенного типа c, используя ключевое слово infer.

interface Wrapped<T> {
  data: T
}

type ExtractGeneric<T> = T extends Wrapped<infer X> ? X : never

function f<T extends Wrapped<any>>(): ExtractGeneric<T> {
  ....
}

const n = f<Wrapped<number>>()
...