Patterns
How do I let callers choose an input and transform without writing type arguments at the call site?
Place type parameters where values reveal them: one in the array element and one in the callback return.
The recipe
function mapValues<T, U>( items: readonly T[], transform: (item: T) => U, ): U[] { return items.map(transform) } const lengths = mapValues(['a', 'four'], text => text.length) const flags = mapValues([1, 2], value => value > 1)
The build compiles this and checks each result below.
How it works
- 01
items: readonly T[]The first argument supplies `T`; `readonly` accepts both mutable and readonly arrays.
- 02
transform: (item: T) => U
Context gives the callback its input, while its returned expression supplies `U`.
What you get
typeof lengths→number[]typeof flags→boolean[]ReturnType<() => ReturnType<typeof mapValues<string, number>>> extends number[] ? true : false
→true
Where it goes wrong
A type parameter used only in the return type cannot be inferred from arguments. Callers would have to spell it or accept a default unrelated to what the function actually returns.
Takeaway
Good generic APIs infer type parameters from ordinary values and use annotations only to express relationships.
