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](https://www.typescriptlang.org/play/?#code/PTAEEFQMwVwOwMYBcCWB7OokAsCGTRcEEBTAByQGdDNcAnAcxgFsS4C0oaaMBPZtDGpJeZEqADu2EnXHY0AIwUoS1FNVxYYZADYkAXAChDsRKgyhKSOijgMUUXgAUZlDAAoxdN3H2gA3oagwaBwuKx+VjZ2ANxBIbgMBqEsCjJxIaDySiqUfgDaUbYMADSW1sUAujGgIFq6JIYAvgCUAfHBskgwdJgABgAk-l4+AHRhrE2g6qBDIxijiSRTvCT01Gg6ACY0OzpoAG6qs8OuC9nKqqMAVmi27gBEu8EPLU2jfXFNxnUIsvjiTSUFDMFA6ehYUQGYwIDBWQh6AAeoAAvO1MhNkgBycBIrElDqEJJ+ABMAAYCZkLrkCliJLgdABrYr40BY2FoZl2LGVWpgaSyNnU1R9aYaOh0XC8MpwNAEbpkBqRCp2fK8gCEaMKKtK5WiDEqzR+YGsvGKWDQoAQDJ0WGk0HgyHQmAkKBwCJIyNw4qYrHYkjBtutQkBmBkdDQdCMhiKdgczjOcHcDM9LRqdQAKlC9cU1WLQnLCJRgQwwgo9BbIWJQNr9WVYwbjaAADIkJBY6hbEgIcGCkTVm0ob0B90KvTR-viFzeCxowIY8LJBsZBLElLMNJ0FfBYV5GsN+s66p8+p6I2GOq4OA7P5rJChuUCwiMFhsDhcHAzSegT26FAIN0dF4aNYTgeEU0REk-GnHxUXREJMT8HE8UpVdknJVCd0US493yOkGS5BhWXZNBORZXk6llCRpgIL9tArNE+lrYpD31So+nPOocDYK0bTtcRTCdDBowbeMYI8CCSTTE8qJojtQAAeUZJsAHU8ForheEEUAtgwLECHpf0kEtW8AR-RE-wA+UoQAflAABJMD71wHYtJgUBmClSQr3lS1bCgGR+KrASI2YILGSozBBPMWgXz9JBRlAAAxSM7XwUA3N4zBTPvQhQCSOAZH-YK0oIa1MH8wKcHS78oFStzRmMb8ksdJKUG8JBwDit8szEAAeDMAD44Izcz72vah3CgdqrD8Sq6FADM2o6spRjW+gGD3K9eDVNoUWG7b4jspaZqQeI-EKo4tybK8diSeV1OCids3EuBHICiUSC2XrxDRFrEGWqwut9HqoT6ydOBzONHFewa4gvMAM3tV73vDL6fvzFAu3Yf8GUrX8dH-QDeB0kgdGtWQdlekrbqy0A0lAEMdm4yxF284CYThAgIIAZmgxNUc+77sznQlELZXFPXxQkllJClCV3Wl6SZFkyhIsjuQosA3XzMdftAJiDyhg0OO+BHeJ0Qm7CC6LnQDS3eJDAsfwlSM8mMUSYcTZMkR56TgAAKlAAA5S0foAZT+FAKBdiNvFAAOwCAA}

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