260

I may have missed something in the docs, but I can't find any way in typescript to get the types of the parameters in a function. That is, I've got a function

function test(a: string, b: number) {
    console.log(a);
    console.log(b)
}

I want access to the types string and number, likely as a tuple.

I know I can get the type of the function itself, as typeof test, or the return type via ReturnType<test>.

When I tried keyof typeof test, it returned never, which I also couldn't explain.

Other answers like this one point to extends, but I don't really understand how that works and don't give me an easy way to access the set-of-all-params as a type.

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
ABMagil
  • 4,579
  • 4
  • 21
  • 35

1 Answers1

484

Typescript now comes with a predefined Parameters<F> type alias in the standard library which is almost the same as ArgumentTypes<> below, so you can just use that instead of creating your own type alias.

type TestParams = Parameters<(a: string, b: number) => void> // [string, number]

Then to get for example the second parameter's type you can use the numeric indexing operator:

type SecondParam = TestParams[1] // number

Original answer:


Yes, now that TypeScript 3.0 has introduced tuples in rest/spread positions, you can create a conditional type to do this:

type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any ? A : never;

Let's see if it works:

type TestArguments = ArgumentTypes<typeof test>; // [string, number]

Looks good. Note that these beefed-up tuples also capture things like optional parameters and rest parameters:

declare function optionalParams(a: string, b?: number, c?: boolean): void;
type OptionalParamsArgs = ArgumentTypes<typeof optionalParams>; 
// [string, (number | undefined)?, (boolean | undefined)?]

declare function restParams(a: string, b: number, ...c: boolean[]): void;
type RestParamsArgs = ArgumentTypes<typeof restParams>;
// [string, number, ...boolean[]]
starball
  • 20,030
  • 7
  • 43
  • 238
jcalz
  • 264,269
  • 27
  • 359
  • 360
  • 27
    Thanks, @jcalz. It appears this functionality is now available in TypeScript itself as `Parameters`. – Stephen Niedzielski Feb 01 '19 at 07:16
  • 1
    what does `infer` keyword mean? – Sang Apr 15 '19 at 02:56
  • 1
    See [Type inference in conditional types](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#type-inference-in-conditional-types) – jcalz Apr 15 '19 at 03:12
  • is it possible to use parameter types of a function to define parameter types of another function when parameters are unknown (...args: any[])? – Erfan Azary Jan 15 '23 at 23:49
  • 2
    nevermind, found it. for anyone wondering, you can do like: `(...args: Parameters) => ....` – Erfan Azary Jan 15 '23 at 23:52
  • @ErfanAzary that didn't work for me. I did this ```ts (...[args]: Parameters) => .... ``` – o-az Feb 09 '23 at 01:06
  • @o-az you have extra brackets around `args` – Erfan Azary Feb 09 '23 at 08:50
  • @ErfanAzary that's on purpose – o-az Feb 10 '23 at 23:18
  • @o-az so what's not working for you exactly? by using `...[args]`, type of `args` will be type of first argument of `anotherFunction` which doesn't seem to be the purpose of naming it `args`, if you want `args` to be list (array) of all arguments, then it should be like `...args`. Please explain a little more specific when you say not working to see whats the problem – Erfan Azary Feb 11 '23 at 10:42
  • What if the function is inside a variable and refers to a method inside an object? – Hendy Irawan Apr 01 '23 at 05:28
  • I can't really answer followup questions in comments on answers to old questions, especially not without a [mre] of the issue. If you can't find an existing answer you might want to post a new question (and then you'll get more eyes on it than just people who follow comments on old questions). – jcalz Apr 01 '23 at 13:54