3

I want to do this

const tuple = ["foo", "bar"] as const

const convert = <T>(x: T): {item: T} => ({item: x})

const convertedTuple: [{item: "foo"}, {item: "bar"}] = tupleMap(tuple, convert)

I have tried this

type TupleMap<T extends readonly any[], Fn extends (item: any) => any> 
  = T extends readonly [infer Head, ...infer Tail]
      ? (Fn extends (item: Head) => infer R
        ? [R, ...TupleMap<Tail, Fn>]
        : never)
      : []

function tupleMap<T extends readonly any[], 
  Fn extends (item: any) => any>(a: T, fn: Fn): TupleMap<T, Fn> {
  return a.map(fn) as any
}

But convertedTuple type is inferenced as [{item: unknown}, {item: unknown}] and I am not sure why.

ais
  • 2,514
  • 2
  • 17
  • 24
  • Array.prototype.map does not work with tuples in a way you expect. SOme time ago TS team was trying to type it but then they revert their changes. I'm tooo lazy to look for links. It such cases you need either to use `as` type assertion or function overloading. I prefer overloadings. See [here](https://tsplay.dev/w65Q0W) – captain-yossarian from Ukraine Apr 23 '22 at 14:33
  • Thanks. Your `tupleMap` depends on `Convert`. Is it possible to write a more generic version? So it would be possible to use it with any convertor. – ais Apr 23 '22 at 15:46
  • 1
    See the answer to the linked question for why this is not possible. There's no real way to ask the type system "given a function `f` of generic type `F extends (arg: I)=>O` and a argument `a` of generic type `A extends I`, what is the type of `f(a)`?" and get an answer more specific than `O`. The compiler won't synthesize a type function for you. Nor can you represent "arbitrary type function" at the type level. So you end up only being able to write `tupleMap()` for hardcoded type functions. – jcalz Apr 23 '22 at 16:36

0 Answers0