Skip to content

Instantly share code, notes, and snippets.

@develax
Last active September 20, 2024 21:16
Show Gist options
  • Save develax/d6a832cfaf89a512b8dd459c514477ef to your computer and use it in GitHub Desktop.
Save develax/d6a832cfaf89a512b8dd459c514477ef to your computer and use it in GitHub Desktop.

Infer Function Argument Type

A function that accepts an argument of an anonymous type where hobbies is a tuple:

function stringifyPerson(person: {
    name: string;
    age: number;
    hobbies: [string, string]; // tuple
}) {
    return `${person.name} is ${person.age} years old and loves ${person.hobbies.join(" and  ")}.`;
}

create a similar type:

const alex = {
    name: 'Alex',
    age: 20,
    hobbies: ['walking', 'cooking'] // here 'hobbies` is array, not tupple: string[] != [string, string]
}

trying to call the function with alex as argument will cause an error:

stringifyPerson(alex); // Type string[] is not assignable to type [string, string]

Let's declare type allias with tuple:

type Person = {
    name: string;
    age: number;
    hobbies: [string, string]; // tuple
}

and create another argument of this type explicitly:

const alex2: Person = {
    name: 'Alex',
    age: 20,
    hobbies: ['walking', 'cooking'] // now it is tuple = `[string, string]`
}

then call the function:

stringifyPerson(alex2); // now it's Ok

What if you don't want to create explicit type? Instead you may want to infer the type from the known function argument. For that you can create a generic type that can infer that type for you.

type FuncFirstArgumentType<T> = T extends (first: infer TFirst, ...args: any[]) => any
  ? TFirst
  : never;

and get that type:

type PersonInferredType = FuncFirstArgumentType<typeof stringifyPerson>;

The PersonInferredType is identical to explicitly delcared Person type and can be used the same way:

const alex3: PersonInferredType = {
    name: 'Alex',
    age: 20,
    hobbies: ['walking', 'cooking'] // it is tuple = `[string, string]`
}

calling the function will cause no errors:

stringifyPerson(alex3); /* No TypeScript errors */ 

PLAYGROUND

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment