Tips for utilizing generic object utilities for objects defined by interfaces in Typescript

I am facing an issue with my code where I have defined an object with an interface and a utility function to clean up the object by removing undefined properties. However, when I try to pass this object to the utility function, Typescript throws an error.

// utils.ts
// removes undefined props from a generic object
const removeEmpty = (obj: Record<string, unknown>): Record<string, unknown> => {
  Object.keys(obj).forEach(key => obj[key] === undefined ? delete obj[key] : {});

  return obj;
};

// some api
interface IMyAPIParams {
  first: string;
  second: string;
  extra1?: string;
  extra2?: string;
}

const baseReq: IMyAPIParams = {
  first: "one",
  second: "two",
};

// some code, that may result in some of these extra properties being present
// but with value of 'undefined'

const req = removeEmpty(baseReq);

/**
 * 1.
 * 
 * Error: Argument of type 'IMyAPIParams' is not assignable to parameter of type 
 * 'Record<string, unknown>'.
 * Index signature for type 'string' is missing in type 'IMyAPIParams'
 */

/**
 * 2.
 *
 * const req = removeEmpty(baseReq as Record<string, unknown>);
 *
 * Error: Conversion of type 'IMyAPIParams' to type 'Record<string, unknown>'
 * may be a mistake because neither type sufficiently overlaps with
 * the other.
 * If this was intentional, convert the expression to 'unknown' first.
 */

I need help to resolve this issue in my code without using @ts-ignore. I believe this issue stems from trying to incorporate typical JS code into TypeScript.

Answer №1

To maintain type information, it is recommended to introduce a generic type T in the function. Additionally, replace unknown with any after applying this change:

const removeEmpty = <T extends Record<string,any>>(obj: T): Partial<T> => {
  Object.keys(obj).forEach(key => obj[key] === undefined ? delete obj[key] : {});

  return obj;
};

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

Upon the second click, the addEventListener function is triggered

When using the window.addEventListener, I am encountering an issue where it only triggers on the second click. This is happening after I initially click on the li element to view the task information, and then click on the delete button which fires the eve ...

Is it possible to utilize TypeScript code to dynamically update the JSON filter with variable values?

I am dealing with a JSON filter in which the value for firmwareversion needs to be replaced with a dynamic value. Here's how I've set it up: //JSON filter this.comX200FilterValue = '{ "deviceType": "ComX", "firmwareV ...

Having trouble with Typescript module path resolution for .js files?

I have embarked on a project in React and I am eager to begin transitioning the js files to typescript. The setup for aliases seems to function smoothly when importing .tsx within another .tsx file, however, it encounters issues when attempting to import . ...

Angular release 6: A guide on truncating text by words rather than characters

I'm currently enhancing a truncate pipe in Angular that is supposed to cut off text after 35 words, but instead it's trimming down to 35 characters... Here is the HTML code: <p *ngIf="item.description.length > 0"><span class="body-1 ...

The JSX element 'SubscribeCard' does not contain any construct or call signatures

I'm looking to implement the react-subscribe-card module for handling email subscriptions in my react.js project. Below is the code snippet from my popup.tsx file: import React from "react"; import SubscribeCard from "react-subscribe-c ...

TS fails to recognize any additional properties added to the constant object

When working on a function that should return an object with properties 'a' and 'b', I am defining the object first and then adding values to it later: const result = {}; result.a = 1; result.b = 2; return result; However, TypeScript i ...

Exploring the process of selecting checkboxes in Angular 6

I'm currently learning Angular 6 and I have a requirement to mark checkboxes based on specific IDs from two arrays: this.skillArray = [ {ID: 1, name: "Diving"}, {ID: 2, name: "Firefighting"}, {ID: 3, name: "Treatment"}, ...

When attempting to utilize the Next.js Head component in a location other than _document, the page experiences

Currently, I am in the process of integrating Next.js with Typescript and Material UI. Despite the abundance of tutorials available online for setting up Next.js with Material UI, I have encountered a commonality among them where they all provide identical ...

Differences between TypeScript `[string]` and `string[]`

When using TypeScript, which option is the correct syntax? [string] vs string[] public searchOption: [string] = ['date']; public searchOption: string[] = ['date']; ...

An action in redux-toolkit has detected the presence of a non-serializable value

When I download a file, I store it in the payload of the action in the store as a File type. This file will then undergo verification in the saga. const form = new FormData(); if (privateKey && privateKey instanceof Blob) { const blob = new Blo ...

Sort and incorporate elements by multiple strings present in an array

Looking to filter and include strings in an array by matching them with items in another array? Here is a sample code snippet that filters based on a single string: const filteredString = `${this.filter}`.toLowerCase(); this.filteredCampaigns = this. ...

Utilize TypeScript Compiler (tsc) without the need for global installation via

Currently, I am tackling a project that needs to be delivered to a group of individuals. This project is written in TypeScript, requiring them to execute the command tsc for compilation. The issue arises when I run this command following the execution of ...

Jest test encounters an error due to an unexpected token, looking for a semicolon

I've been working on a Node project that utilizes Typescript and Jest. Here's the current project structure I have: https://i.stack.imgur.com/TFgdQ.png Along with this tsconfig.json file "compilerOptions": { "target": "ES2017", "modu ...

Increasing the token size in the Metaplex Auction House CLI for selling items

Utilizing the Metaplex Auction House CLI (ah-cli) latest version (commit 472973f2437ecd9cd0e730254ecdbd1e8fbbd953 from May 27 12:54:11 2022) has posed a limitation where it only allows the use of --token-size 1 and does not permit the creation of auction s ...

angular component that takes a parameter with a function

Is there a way for my angular2 component to accept a function as a parameter? Uncaught Error: Template parse errors: Can't bind to 'click' since it isn't a known property of 'input'. (" minlength="{{minlength}}" [ERROR -&g ...

Error encountered in Ngrx data service when using Angular resolver

I have successfully implemented an NGRX Data entity service and now I'm looking to preload data before accessing a route by using a resolver. import { Injectable } from "@angular/core"; import { ActivatedRouteSnapshot, Resolve, RouterS ...

Tips for correctly specifying the types when developing a wrapper hook for useQuery

I've encountered some difficulties while migrating my current react project to typescript, specifically with the useQuery wrappers that are already established. During the migration process, I came across this specific file: import { UseQueryOptions, ...

The Angular tag <mat-expansion-panel-header> fails to load

Every time I incorporate the mat-expansion-panel-header tag in my HTML, an error pops up in the console. Referencing the basic expansion panel example from here. ERROR TypeError: Cannot read property 'pipe' of undefined at new MatExpansionPanel ...

Converting Typescript Object Types to Array Types with Tuple Structures

Presently, I have the following: interface Obj { foo: string, bar: number, baz: boolean } The desired outcome is to convert this interface into the tuple format below: [string, number, boolean] Is there a way to achieve this conversion? Up ...

Working with nested arrays in TypeScript and how to push values onto them

I am facing some challenges with nested array behavior in TypeScript. I am looking for a way to define a single type that can handle arrays of unknown depth. Let me illustrate my issue: type PossiblyNested = Array<number> | Array<Array<number& ...