Creating a versatile TypeScript Record that can accommodate multiple data types

I have a question regarding the use of Record in TypeScript. When I specify Record as the parameter type in a function, I encounter an error in my code because it does not allow different types.

type Keys = 'name' | 'qty';

const getValueByKey = <T = any>(items: Record<Keys, T>, key: Keys) => {
  return items[key];
}
getValueByKey({ name: 'fulan', qty: 1}, 'name'); // Error: Type 'number' is not assignable to type 'string'.(2322)

TypeScript Playground

The main aim is to determine the type of the value within the function.

Is there a way to make a Record accept values of varying types? Thank you

Answer №1

It appears that you are looking to create a function that accepts an object type with specific keys in a union, and returns a value based on the provided key parameter while also inferring the valid key parameters from the object itself. This can be achieved using generic constraints.

Remember that TypeScript follows structural typing, meaning any object with keys like `name` and `qty` will be accepted (even if additional keys exist), allowing you to use any of those keys as arguments for the function.

TS Playground

type Key = 'name' | 'qty';

function getValueByKey <
  T extends Record<Key, any>,
  K extends keyof T,
>(items: T, key: K): T[K] {
  return items[key];
}

const obj = {name: 'fulan', qty: 1};

const value1 = getValueByKey(obj, 'name');
    //^? const value1: string

const value2 = getValueByKey(obj, 'qty');
    //^? const value2: number


If you attempt to use a key not present in the object, TypeScript will generate a compiler error:

const value3 = getValueByKey(obj, 'not_a_key');
//                                ~~~~~~~~~~~
// Argument of type '"not_a_key"' is not assignable to parameter of type '"name" | "qty"'. (2345)

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

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 is the best way to sort an array based on a person's name?

I have a list of different groups and their members: [ { "label": "Group A", "fields": [ { "value": "color1", "name": "Mike" }, { &quo ...

Executing an HTTP POST request without properly encoding a specific parameter

I am attempting to communicate with an unauthorized third-party API using Node and the request module. Below is the code that generates the request: request.post( { url: url, headers: MY_HEADERS_HERE, followAllR ...

Updating part of an object using TypeScript

I am looking to create a utility function that takes an instance and an object as input, and then updates the instance with the values from the provided object fields. Below is the code for the utility function: function updateEntity<T, K extends keyof ...

Protractor experiencing difficulty recognizing Angular functionality

Recently, I made the switch to using Protractor for running end-to-end tests on my Angular application. However, the e2e tests have suddenly started failing because Protractor is unable to detect Angular on the website. I raised this issue in their GitHub ...

Define the state of an object using Parent and Children classes following the application of a filter

Within Angular 8, I am dealing with an Observable: let parents: Observable<Parent[]>; The classes Parent and Child are defined as follows: class Parent { id: number; name: string; children: Child[]; } class Child { id: number; name: str ...

Combining namespaces in Typescript declaration files

Currently, I am attempting to combine namespaces from d.ts files. For example, when I attempt to merge namespaces in a single file, everything works as expected. declare namespace tst { export interface info { info1: number; } var a: ...

Guide on enabling external API login with Next Auth v5 in Next.js 14 using the application router

While trying to navigate the documentation for Next Auth, I found myself struggling with outdated examples and an overall lack of clarity. It appears that the documentation is still a work in progress, making it challenging to find reliable information on ...

Updating an array in a single line of code in Javascript can be achieved

Can the code below be optimized? const item: any; // New data const index: number = basketModel.data.coupons.findIndex( (x: any) => x.couponId === item.couponId ); if (index === -1) { // If new item, push it to array ...

What could be the reason for the inconsistent behavior of onClick, causing it to occasionally fail to display the associated

I just started using typescript 2 days ago, mainly to create a custom component for my streamlit app. I've made a navigation bar with a tab that can be clicked on the sidebar, but it's displaying some erratic behavior. Sometimes when I click on t ...

Reactjs Promise left hanging in limbo

How can I resolve the pending status of my promise? I have a modal with a form submit in it, where I am trying to retrieve the base64 string of a CSV file. While my code seems to be returning the desired result, it remains stuck in a pending state. c ...

Is there a way to transform this unusual string into JSON format using Python?

Is there a way to transform this string into JSON format using Python? >>> data = '[for: css=a[title="See LLCAutoSept files"]]' >>> json.dumps(data) '"[for: css=a[title=\\"See LLCAutoSept files\\"]]"&ap ...

Updating Previous and Next links in an Angular Table following row deletions: A step-by-step guide

I need to implement a feature where row elements can be deleted by enabling checkboxes on the rows and clicking the Delete button. Although I am able to successfully delete items from the table upon clicking the Delete button, I am facing challenges in upd ...

Incorporating TypeScript basics into the if statement post compiling

As I delve into the Angular2 Quickstart, I stumbled upon a peculiar issue within app.component.js after compiling app.component.ts using tsc (version 1.8.2): if (d = decorators[i]) I am unable to pinpoint where I may have gone wrong in configuring the qu ...

Customized IntelliSense naming for overloaded parameters with conditional tuple types

In TypeScript 3.1, I have a generic function with arguments of either (TInput, string) or (string), depending on whether the generic's type parameter TInput extends undefined. To achieve this, I'm utilizing the new generic rest parameters feature ...

Issue encountered with ng-include compatibility in Angular 5

Just getting started with Angular and working on a small test project using Angular 5 and Visual Code. I'm attempting to use ng-include but the template is not displaying. src add-device add-device.component.html add-device.com ...

Merging two arrays concurrently in Angular 7

When attempting to merge two arrays side by side, I followed the procedure below but encountered the following error: Cannot set Property "account" of undefined. This is the code in question: acs = [ { "account": "Cash In Hand", ...

Discover the process of accessing and setting values in Angular 8 to easily retrieve and manipulate data from any page!

Greetings! I am currently utilizing Angular 8 and I have a query regarding how to access the set value in any given page. Here is a snippet of my code: class.ts export class testClass { get test():string{ return this.sexe; } ...

Modifying the website favicon based on the URL address

I am currently working with a client who wants our web application to reflect their branding through the URL. They have requested that we change the favicon on the page to display their private label logo, as well as changing the title. However, I am strug ...

Error: TypeScript cannot find @types declaration for restify-client

Currently, I am attempting to upgrade to the most recent version of restify (6.4.2). Our application is written in TypeScript. The clients have now been separated into their own package starting from the previous version of restify we were using (4.3.2) - ...