4

Consider the following piece of code:

const f = (a: number, b?: string) => 2;

type ParametersOfF = Parameters<typeof f>; // [number, string?]
type AsTuple = [number, string?]; // [number, string?]

declare function g(...args: ParametersOfF): number; // function g(a: number, b?: string): number !!!
declare function h(...args: AsTuple): number; // function h(args_0: number, args_1?: string): number

So ParametersOfF and AsTuple are the same type. But when I define functions which take args these 2 tuples, g have well defined argument names a and b, while h has args_0 & args_1.

Hence the title of this post: Parameters<F> is not a simple tuple, it contains also the names of each element in said tuple. Looking at how Parameters is defined doesn't help, it's quite simple. So what's the magic?

1 Answer 1

4

The reason has to do with compiler internals not so much with the Parameters type itself. Any similar conditional type you write will preserve parameter names.

For tuples extracted from parameters , the compiler keeps a reference to the original parameter each tuple item was extracted from. When the tuple is spread back to a function the original name is used.

This association is not something directly visible from the type system and there is no way to set this tuple item name, it's a hidden property of the tuple.

Sign up to request clarification or add additional context in comments.

1 Comment

documented here, "Note that when a tuple type is inferred from a sequence of parameters and later expanded into a parameter list, the original parameter names are used in the expansion (however, the names have no semantic meaning and are not otherwise observable)."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.