The value of 'number' can be assigned to the constraint 'T[keyof T]', however, there is a possibility that 'T[keyof T]' may be initialized with a different subtype of the constraint 'number'

The code below shows how I am attempting to sum each property of an array of T and return it as T:

export function sumProperties<T extends { [k: string]: number }>(values: T[]): T {
  return values.reduce((acc, cur) => {
    (Object.keys(cur) as Array<keyof T>).forEach((k) => {
      acc[k] = (acc[k] || 0) + cur[k];
    })
    return acc;
  }, {} as T);
}

The line acc[k] = (acc[k] || 0) + cur[k]; is causing issues in the code.

Currently, I have a workaround using

Object.assign(acc, { [k]: (acc[k] || 0) + cur[k] });
but I would prefer not to use it. Can anyone explain the reason for this error and suggest a TypeScript safe solution?

Answer №1

The issue arises from the fact that T extends {[k: string]: number} does not guarantee that the values of T are strictly numbers; they could also be literal numbers like {type: 1}:

// true
type Case1 = 1 extends number ? true : false

// false
type Case2 = number extends 1 ? true : false

const a: {type: 1} = {type: 1}

const a.type = 2; // error

In essence, T can include some sub-types of number as values that cannot be altered, leading to uncertainty for the compiler in terms of modification.

A possible solution would be to eliminate generics altogether, but if you still require them, one approach could be something like this, although it only provides generic functionality for keys and not values:

export function sumProperties<T extends { [k: string]: number }>(
  values: Record<keyof T, number>[],
): Record<keyof T, number> {
  return values.reduce((acc, cur) => {
    (Object.keys(cur) as Array<keyof T>).forEach((k) => {
      acc[k] = (acc[k] || 0) + cur[k];
    });
    return acc;
  }, {} as T);
}

While we still utilize T as a generic parameter, we define values as Record<keyof T, number>, enabling modifications.

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

Converting a string to a number is not functioning as expected

I am facing a problem with an input shown below. The issue arises when trying to convert the budget numeric property into thousands separators (for example, 1,000). <ion-input [ngModel]="project.budget | thousandsSeparatorPipe" (ngModelChange)="projec ...

Ways to create a method that can be overridden

Is there a way to declare a virtual method in TypeScript? I'm attempting to achieve something similar to the following: export abstract class SuperClass { public virtual enable(enableComponents: boolean): void { } } ...

Issue: The function (0, react__WEBPACK_IMPORTED_MODULE_1__.useActionState) is not recognized as a valid function or its output is not iterable

I found a great example of using useActionState at this source. Currently, I am implementing it in my project with Next.js and TypeScript. app/page.tsx: "use client"; import { useActionState } from "react"; import { createUser } from ...

Using TypeScript to interpret JSON - insert a 'data' label

Consider the following example of a JSON structure: [ { "id":1, "position":3, "articleNumber":"ServiceElement" }, { "id":2, "position":2, "articleNumber":"ServiceElement" } ] Is there a way to transfo ...

Using TypeScript to send state through history.push({...})

I recently utilized the history.push method to redirect to a specific URL while passing along some information through the included state. Here's how I implemented it: const history = useHistory() history.push({ pathname: '/someurl/', ...

What is the reason that specifying the type of function parameters does not result in conversion being

Seeking clarity here. I have a TypeScript function (using version 1.7) that is linked to the change event of a select dropdown in HTML: toggleWorker(stsID: number): void { // get status object by selected status ID let cStatus: Status = this.s ...

Value in Hook not updating after memoization of parent component

Let's consider this scenario: import * as React from "react"; const useMyHook = ({ element }: { element: HTMLElement | null }) => { React.useEffect(() => { if (element) { console.log("element in hook", element); ...

Error arises when attempting to pass interface props to a component in a React Typescript application

I am currently delving into the world of React js and typescript. As part of my learning process, I have created a demo application that allows users to input their name and age. The app features an ErrorModal that should pop up on the screen whenever inco ...

The conversion of an array to Ljava/lang/Object is not possible

I'm currently working on a project using NativeScript app with TypeScript where I am trying to pass an array of android.net.Uri to a function. However, when attempting to do so, I encounter an error mentioning that the 'create' property does ...

I continue to encounter the same error while attempting to deliver data to this form

Encountering an error that says: TypeError: Cannot read properties of null (reading 'persist') useEffect(() => { if (edit) { console.log(item) setValues(item!); } document.body.style.overflow = showModal ? "hidden ...

Using Typescript for Asynchronous Https Requests

I've been attempting all day to make an https request work. My current code isn't functioning as expected; when I run it, I encounter an "Unhandled error RangeError: Maximum call stack size exceeded at Function.entries" import * as https from &q ...

unable to retrieve access-token and uid from the response headers

I am attempting to extract access-token and uid from the response headers of a post request, as shown in the screenshot at this https://i.sstatic.net/8w8pV.png Here is how I am approaching this task from the service side: signup(postObj: any){ let url = e ...

Implementing method overrides in TypeScript class objects inherited from JavaScript function-based classes

I am facing a challenge with overriding an object method defined in a JavaScript (ES5) function-based class: var JSClass = function() { this.start = function() { console.log('JSClass.start()'); } } When I call the start() method, it pri ...

There is no index signature in the type 'string | number | EnvType' that accepts a parameter of type 'string'

Can someone help me troubleshoot this issue with config[curr][targetEnv] ??? interface EnvType { dev: string; staging: string; production: string; } type Config = { [key: string]: number | string | EnvType; }; const config: Config = { network ...

What is the process for including a selected-by option in a VIS network graph?

I'm trying to outline the neighboring nodes of the node that has been selected (highlightNearest). https://i.sstatic.net/lynhu.png Unfortunately, I haven't had success achieving this using JavaScript. Link to StackBlitz ...

Configure Typescript to skip errors for a specific file

Is there a way to suppress TypeScript errors for specific files using the tsconfig.json file? I am aware of the exclude property mentioned on the TypeScript website, but that's not exactly what I'm looking for. As it's explained: If a fil ...

What is the official name of the key type for the Built-in Object?

There was a built-in type that I used in the past which represented the union of all possible object keys. It was named objectKey or something similar. Here is an example: type objectKey = string | number | symbol Unfortunately, I am drawing a blank on t ...

Utilizing the power of HTML5 drag and drop functionality in conjunction with Angular Material 2's md

When working with Angular Material 2 and attempting to enable reordering of list elements, I encountered an issue where the functionality works perfectly for li-tag but fails with md-list-item. Why is that? Here is a snippet of my template: <md-nav-li ...

Discover the steps to declare and sign up for queryParams within Angular

Let's break down this issue from two different perspectives - the user's and the developer's. The user's perspective: Upon clicking "Edit Server", the user expects to be able to edit the server. However, this functionality is not work ...

What is the best way to forward all URLs to one central page?

I've recently started working with Angular and I'm currently developing a web app project using Angular 9. I could really use your help with this. My goal is to have a dynamic URL structure for the web app, such as https://www.myMainURL.com/***, ...