Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to narrow down types of a const

In the example below, I would like to mandate that all functions should return in a specific format [string, number], but input arguments for those functions can vary.

Playground link

type ReturnFormat = [string, number]
type Fn = (...args: any[]) => ReturnFormat

const A: Fn = () => ['one', 1]
const B: Fn = (input: number) => ['two', input]

type C = Parameters<typeof A>
type D = Parameters<typeof B>

However, when I try to read back the parameters of the function, both C and D are any[], and not null and input: number. What should I do to make that happen?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem here is that you are declaring the variables A and B with the type Fn. The type Fn only knows that the arguments should be of type ...any[]. So when you use this type to declare variables, any specific information about the actual functions you used for the assignment is lost.

You should instead use a generic function to initialise the functions.

function createFunction<T extends Fn>(fn: T) { return fn }

We can constrain the passed function T to be of type Fn, but we still return a function of the original type T.

When we use this function to create the two variables, you will see that the type information is preserved.

const a = createFunction(() => ['one', 1])
// const a: () => [string, number]

const b = createFunction((input: number) => ['two', input])
// const b: (input: number) => [string, number]

const c = createFunction((input: number) => ['two']) // Error: We broke the constaint!

Playground


A second option would be to make Fn generic. But we would have to explicitely give the parameter type to Fn everytime we use it to declare a function.

type Fn<T extends any[] = void[]> = (...args: T) => ReturnFormat

const a: Fn = () => ['one', 1]
const b: Fn<[number]> = (input: number) => ['two', input]
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading