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

Typing a function based on the argument value

Suppose I have the following JS function:

function extractProperty(propName) {
    return x => x[propName];
}

Can I type extractProperty s.t. by Typescript’s type inference I get the following:

const x = { first: 1, second: "two" };
const y = { first: [1], second: 2 };
// or any other object having first and second

const a1 = extractProperty("first")(x); // a1 should be of type number
const a2 = extractProperty("second")(x); // a2 should be string
const a3 = extractProperty("first")(y); // a3 should be number[]
const a4 = extractProperty("second")(y); // a4 should be number

const getFirst = extractProperty("first");
// getFirst should be <T> (t: T) => T["first"]

const getSecond = extractProperty("second");
// getSecond should be <T> (t: T) => T["second"]

If rather than a parameter propName, I had a fixed property name, I could probably do the following:

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

function extractPropertyFirst ():
<TFirst> (x: { first: TFirst }) => TFirst

or, slightly more in the direction of what I want to achieve,

function extractPropertyFirst ():
<T> (x: T) => T["first"]

Yet how can I make typescript take the argument of the function as the property name?

I have played around with the following approach, yet without success:

function getProperty<K> (propName: K):
<TProp> (t: { [K]: TProp }) => TProp {
    return x => x[propName];
}

Typescript does not accept a general K as the indexing type.

>Solution :

You can make getProperty work by using {[Key in K]: TProp}, or equivalently, Record<K, TProp> for the type of t, and adding an K extends PropertyKey constraint:

function extractProperty<K extends PropertyKey>( propName: K):
  <TProp>(t: Record<K, TProp>) => TProp {
    return (x) => x[propName];
  }

const a1 = extractProperty("first")(x);
// type: number

const a2 = extractProperty("second")(x)
// type: string

const a3 = extractProperty("first")(y);
// type: number[]

const a4 = extractProperty("second")(y);
// type: number

TypeScript playground

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