What is preventing me from writing to an object property using index type inference?

I am struggling with this particular function

function foo<T extends { [P in K]: number }, K extends keyof T>(obj: T, key: K): void {
  const x: number = obj[key]
  obj[key] = 123 //error
}

obj[key] is of type number, yet it doesn't allow writing numbers to it.

The error states: Type '123' is not assignable to type 'T[K]'.

Anyone has any ideas on how to resolve this issue?

Answer №1

Everything is functioning as anticipated. Picture yourself calling the foo function like this:

const obj = {a: 42} as const
foo(obj,"a") 
// foo<{readonly a: 42; }, "a">(obj: { readonly a: 42; }, key: "a"): void

In this scenario, T[K] would not be of type number, but rather 42 (which is a subtype) - attempting to assign 123 to a would no longer be valid. Within the body of the foo function, we can only be certain that T[K] represents some sort of number due to the generic constraint on T, but we cannot determine the exact type.

Therefore, TypeScript will generate the error message

Type '123' is not assignable to type 'T[K]'
- the compiler cannot guarantee that 123 is the correct type since generic types are dictated by the caller of the foo function. The only statically checkable type is T[K].

To allow writing number to specific properties K, you can modify the function signature as shown below:

function foo<K extends PropertyKey>(obj: Record<K, number>, key: K): void {
  const x: number = obj[key]
  obj[key] = 123 
}

const obj = { foo: 1, bar: true }
foo(obj, 'foo') // it will work

Sample on TS 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

Utilizing const as the iteration variable in a for loop

I've grasped the concept of using var and let in a for loop in typescript/javascript, but can someone shed light on how and why a const variable as a loop variable behaves? for (const i = 0; i < 5; i++) { setTimeout(function() { console.log( ...

The yarn/npm package manager seems to be utilizing outdated code in an inexplicable way when paired with mocha and typescript

I recently encountered a strange issue that has left me scratching my head. When I manually run my test command, I receive two test results. However, when I execute the same command in a yarn/npm script, only one result is displayed. Has anyone else experi ...

Is there a way for me to program the back button to navigate to the previous step?

I am currently developing a quiz application using a JSON file. How can I implement functionality for the back button to return to the previous step or selection made by the user? const navigateBack = () => { let index = 1; axios.get('http ...

Ensuring the accuracy of nested objects through class validator in combination with nestjs

I'm currently facing an issue with validating nested objects using class-validator and NestJS. I attempted to follow this thread, where I utilized the @Type decorator from class-transform but unfortunately, it did not work as expected. Here is my setu ...

Limit function parameters to only accept values with matching keys

I am relatively new to using TypeScript and am currently working on a project that involves handling various shapes of data from different sources. My goal is to pass this data to different aggregator classes, with one aggregator class corresponding to eac ...

Introducing a new element in TypeScript using a separate method with parameters

Currently, I am attempting to create a method that will allow me to add an element to my array. Despite being new to typescript, I have been struggling to determine what needs to go into the addNewProduct function. While seeking help, I came across the p ...

What steps can I take to ensure that the elements are in the same row instead of being displayed in three separate rows?

(I'm a beginner in web development and need some help) Is there a way to align elements into the same row instead of stacking them up in separate rows? I'm working on creating a header bar similar to the one on the Naive UI Documentation Website. ...

The TypeScript class for Date has a property that outputs a string

In my TypeScript code, I have defined a model class as follows: export class Season { ID: number; Start: Date; } Below is an example of how this model class is utilized within a component: export class SeasonsComponent { seasons: Season[]; sele ...

Retrieve a HashMap through an HTTP GET request using Angular 10

I am currently using the following versions: Angular CLI: 10.0.1 Node: 12.18.2 OS: win32 x64 Angular: 10.0.2 In my setup, I have a Java Spring Boot service that is functioning correctly and returns data as a HashMap. Map<String, List<String>&g ...

Why is it necessary to omit node_modules from webpack configuration?

Check out this webpack configuration file: module.exports = { mode: "development", entry: "./src/index.ts", output: { filename: "bundle.js" }, resolve: { extensions: [".ts"] }, module: { rules: [ { test: /\.ts/ ...

Attaching an event listener to elements with a specified Class name

Currently facing a challenge where I am trying to implement a function that captures click events on squares. The objective is to capture the click event on every button with the square class. import { Component, OnInit } from '@angular/core&apos ...

Sending the value of "username" between two components within Angular 2

I have a good understanding of nesting child components within parent components in Angular 2, but I'm a bit unclear on how to pass a single value from one component to another. In my scenario, I need to pass a username from a login component to a cha ...

Issue arising from using setCollideWorldBounds and overlap in Phaser 3

I'm facing an issue with Phaser 3. Whenever I use setCollideWorldBounds, I get an error saying "Cannot read property 'setCollideWorldBounds' of null" and the overlapping function doesn't seem to work. What's even more strange is t ...

How come code suggestion works flawlessly on Stackblitz, yet fails to function in Intellij?

Check out this GitHub repository for a simple way to reproduce the issue: https://github.com/tmtron/mathjs-typescript-types Successful Code Completion in Stackblitz Everything works perfectly when you open the project in Stackblitz: https://i.stack.imgur ...

A type guard for generics in TypeScript

I'm dealing with a variable that can be either of type C1[] or C2<C1>[]. How can I create a type guard for this variable? interface C<T>{ key: string; secret: T; } private isC(d: Foo[] | C<Foo>): d is C<Foo>[] { ret ...

Maintaining accurate type-hinting with Typescript's external modules

Before I ask my question, I want to mention that I am utilizing Intellij IDEA. In reference to this inquiry: How do you prevent naming conflicts when external typescript modules do not have a module name? Imagine I have two Rectangle classes in different ...

Having trouble loading JSON file contents into an array in Typescript

I am struggling to load my API keys from a JSON file named api.json. The file structure is as follows: { "service1": ["apikey1", "apikey2"], "service2": ["apikey1", "apikey2"] } In order to manag ...

How can I implement a redirect back to the previous query page post-authentication in Next.js 13?

To enhance security, whenever a user tries to access a protected route, I plan to automatically redirect them to the login page. Once they successfully log in, they will be redirected back to the original protected route they were trying to access. When w ...

An error occurs when attempting to create a document using the context.application.createDocument method in the Word Javascript

The Scenario As I work on developing a Word add-in using the latest Javascript API's for Office, I have incorporated various functionalities along with templates. One of the client's requests is to have the templates accessible from the ribbon. ...

Encountered an error while defining a Vue component using TypeScript with the @Prop decorator

When working with Vue.js and TypeScript, I usually use the following syntax: @Component({ props: ['uploadUrl'], }) export default class SelectionModal extends Vue { let x = this.uploadUrl // This variable `uploadUrl` is NOT resolve ...