Creating a function that operates according to the input parameter

Imagine a scenario where I am working with the following JS function:

function fetchValue(keyName) {
    return x => x[keyName];
}

Is it possible to define fetchValue in such a way that Typescript's type inference automatically determines the output based on the provided examples:

const obj1 = { name: "John", age: 30 };
const obj2 = { name: "Alice", age: 25 };

const result1 = fetchValue("name")(obj1); // result1 should be of type string
const result2 = fetchValue("age")(obj2); // result2 should be number

const getName = fetchValue("name");
// getName should have signature: <T> (t: T) => T["name"]

const getAge = fetchValue("age");
// getAge should have signature: <T> (t: T) => T["age"]

If instead of passing a parameter keyName, I knew the fixed property name, I could potentially do something like this:

function fetchName():
<TName> (x: { name: TName }) => TName

or explore a slightly different route towards achieving my goal:

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

But how can I make Typescript assign the argument of the function as the property name?

I've experimented with various approaches, but haven't found success yet:

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

Typescript seems reluctant to accept a generic K as the indexing type.

Answer №1

To implement getProperty, you can utilize either {[Key in K]: TProp} or Record<K, TProp> as the type for t, along with a constraint of K extends PropertyKey:

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

Check it out on TypeScript playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Enhance your Vue 3 projects with a dynamic library featuring universal components and full

Currently, I am in the process of developing a Vue 3 component library using Vue 3, Vite, and TypeScript. The unique aspect about this library is that it installs as a plugin and registers all components as global entities. Here is an overview of how this ...

When the boolean is initially set to false, it will return true in an if statement without using

My Angular component contains a component-level boolean variable and an onClick event. Here's what the HTML file looks like: <div class="divClass" (click)="onClick($event)"></div> The relevant code from the TypeScript file is as follows: ...

Create a TypeScript class object with specified constructor arguments

I've been working on a function that is supposed to execute the init method of a class and then return an instance of that class. However, I'm running into issues with maintaining the constructor and class types. This is what I have tried so far ...

What is the best way to compare two TypeScript object arrays for equality, especially when some objects may have multiple ways to be considered equivalent

Currently, I am in the process of developing a cost function for a game where players are given a set of resources in their hand. The resources can be categorized into different types such as Fire, Air, Water, Earth, Good, Evil, Law, Chaos, and Void. Thes ...

Developing a collection of components with customizable color variations using React

I am interested in creating a React component library where users can specify color variants. For instance, I want to use the following syntax: const customTheme = createCustomTheme({ button: { variants: { primary: 'primary ...

Accessing the 'comment' property within the .then() function is not possible if it is undefined

Why does obj[i] become undefined inside the .then() function? obj = [{'id': 1, 'name': 'john', 'age': '22', 'group': 'grA'}, {'id': 2, 'name': 'mike', &apo ...

The redirection code is not being executed when calling .pipe() before .subscribe()

My AuthService has the following methods: signUp = (data: SignUp): Observable<AuthResponseData> => { const endpoint = `${env.authBaseUrl}:signUp?key=${env.firebaseKey}`; return this._signInOrSignUp(endpoint, data); }; signIn = (data: SignIn): ...

Utilizing getServerSideProps and getInitialProps in Next.js to optimize page loading times

My page is not loading when I use getServerSideProps or getInitialProps. It keeps on loading without displaying the content, but everything works fine when I remove them. What could be wrong with my code here? HELP. ... interface Props { data: any; } co ...

Angular Firebase Email Verification sent to an alternate email address

I am facing a challenge with my website that only accepts emails from a specific domain, such as a university domain. Users who want to sign up using Facebook or Google need to verify their university email, but I am struggling to find a way to send the ve ...

Change object values to capital letters

Upon retrieving myObject with JSON.stringify, I am now looking to convert all the values (excluding keys) to uppercase. In TypeScript, what would be the best way to accomplish this? myObj = { "name":"John", "age":30, "cars": [ { "name":"Ford", ...

NextImage's ImageProps is overriding src and alt properties

I've created a wrapper called IllustrationWrapper that I'm utilizing in different components. import Image, { ImageProps } from 'next/image'; const getImageUrl = (illustrationName: string) => { return `https://my-link.com/illustra ...

What are the distinctions between generic and discriminated types?

Hi there, I've been thinking of an idea but I'm not sure how to implement it or if it's even possible. Is there a way to create a type SomeType where the first property can be any value from the set T, but the second property cannot be the ...

The implementation of useState is not functioning properly when used within a parent useState function

I am currently working with a Ticket child class where I set the total amount after changing the number of tickets. The issue I am encountering is that the setNumber function doesn't seem to work properly unless the setTotal function is commented out. ...

To run multiple environments with react-native-dotenv in a React Native project using Typescript, only the local environment is activated

Currently, I am facing an issue while trying to initialize my React Native app with TypeScript in three different environments - development, local, and testing. When I attempt to run APP_ENV=testing expo start or APP_ENV=development expo start, it always ...

Setting the sidebar width for Nebular with two sidebars in the layout: A step-by-step guide

Having two sidebars (identified as left and right) in my page layout, I initially set both sidebars to a width of 400px using the custom theme method with sidebar-width: 400px. However, I now need to change the width of the right sidebar to 700px. Is the ...

Triggering an event from a component to its parent module resulting in an exception situation

Here is my app.component.ts code: import { Component, Input, OnInit, OnChanges, SimpleChanges} from '@angular/core'; import {Counter } from './counter' @Component({ selector: 'my-app', template: ` <custom-counter [ ...

Navigate through collections of objects containing sub-collections of more objects

The backend is sending an object that contains an array of objects, which in turn contain more arrays of objects, creating a tree structure. I need a way to navigate between these objects by following the array and then back again. What would be the most ...

Error encountered during Typescript compilation: The attribute 'raw' is not found within the context of the entity 'e' in express

In many instances, I have noticed that people use express.raw() or express.raw({type: 'application/json'}) as middleware in their requests... but is .raw() a legitimate method in Express? I am currently working with TypeScript and using Express ...

Create a function that accepts a class as a parameter and outputs an object of that class

I am working on an instantiator function that generates an instance of a provided class: declare type ClassType = { new (): any }; // known as "ParameterlessConstructor" function createInstance(constructor: ClassType): any { return new constructor(); ...

Utilizing Typescript with Angular 2 to efficiently convert JSON data into objects within HTTP requests

I am dealing with a file called location.json, which contains JSON data structured like this: { "locations": [ { "id": 1, "places": [ { "id": 1, "city": "A ...