Search code examples
typescript

Can I infer a tuple type from a function's return type, without using 'as const'?


I want to use a function that constructs an array as an argument, where each element may be a different type. The order of types is relevant and I need to preserve their order as a Tuple. Here is one way:

const create = <T>(spec: (...args: any[]) => T) => spec;
const result = create(() => ['a', 2, 'a'] as const);
type t = ReturnType<typeof result>; // t is ['a', 2, 'a']

However, this means the developer has to remember to add as const every time they use create.

In my use case, the order of types is always relevant and the function should always receive a Tuple.

Is there any way to force Typescript to always infer the Tuple from the return type without needing as const?


Solution

  • You can hint to the compiler that a generic type argument should be inferred as a tuple type if you specify the constraint of it as [any] | any[].

    const create = <T extends [any] | any[]>(spec: (...args: any[]) => T) => spec;
    const result = create(() => ['a', 2, 'a']);
    type t = ReturnType<typeof result>; // t is [string, number, string]
    
    

    Playground Link


    It doesn't seem possible to infer the literal constant such as ['a', 2, 'a'].