Ways to transfer specific properties from one object to another in TypeScript

I'm currently working on a function that selectively copies key-value pairs from one object to another in order to remove certain properties. The code snippet for this function is shown below:

sanitizeData: function (sourceObject: object, ...allowedKeys: string[]) {
    const sanitizedObject = {};
    Object.keys(sourceObject).forEach((key: string) => {
      if (allowedKeys.includes(key)) {
        sanitizedObject[key] = sourceObject[key];
      }
    });
  }

The purpose of this function is to take an object (e.g., req.body) and a list of strings as input, then perform the specified operation. For instance, an input may look like:

sanitizeData(req.body, 'name', 'age', 'email')
.

This code works seamlessly in JavaScript, however, when trying to run it in TypeScript, I encounter the following error message:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'.
  No index signature with a parameter of type 'string' was found on type '{}'.

If anyone knows how to resolve this TypeScript error, your help would be greatly appreciated.

Answer №1

Here is an innovative solution that intelligently chooses the keys you provide and upholds the typings in the output.

// To ensure that the object you pass extends a record with string keys,
// we use any as a workaround for now, there might be a better way to do this
function sanitize<T extends Record<string, any>, K extends keyof T>(obj: T, ...keys: Array<K>): Pick<T, K> {

  // We implement your code in a different manner while maintaining its functionality
  return Object.entries(obj).reduce((a, [k, v]) => {

    // Here, I opted for find due to the limitation of includes accepting only strings
    if (keys.find((a) => a === k)) {
      a[k as K] = v;
    }
    return a;
  }, {} as Pick<T, K>);
}

// Testing the function with sample data should yield the expected results.
const test = {
  a: 1,
  b: 4,
  c: 6
};

const output_a = sanitize(test, 'a', 'b');

// This will generate a type error
output_a.c;
// No type error will occur here
output_a.a;

console.log(output_a);

It's important to note that even though generics are defined within the function, they don't need to be explicitly specified during invocation when the arguments provide enough context. Thus, the generics are implicitly inferred.

Check out my playground.

Answer №2

If you're looking to maximize code reuse, here's a TypeScript snippet that can help:

const allowed: Array<string> = ['key1', 'key3']
const body = {
  'key1': 1,
  'key2': 2,
  'key3': 3
}

function sanitizeBody (obj: Record<string, any>, allowed: Array<string>): Record<string, any> {
  const sanitizedObject: Record<string, any> = {};
  Object.keys(obj).forEach((el: string) => {
    if (allowed.includes(el)) {
      sanitizedObject[el] = obj[el];
    }
  })
  return sanitizedObject
}

const output = sanitizeBody(body, allowed)

The resulting output will be:

{
  "key1": 1,
  "key3": 3
} 

Ensuring that you provide TypeScript with the correct types will allow it to work seamlessly as intended.

Answer №3

Understanding Index Signatures in TypeScript

When working with typescript, it is essential to grasp the concept of index signatures. These are used when the properties' names are unknown but we know the shape of their values. By providing an index signature, we can define the values and specify the type of index associated with them.

If typescript is unable to interpret the index signature for an object type like in your case, it becomes necessary to explicitly define it. Here is a common approach to defining the index signature:

type IndexSignature = {
  [key: string]: string; //in this example, the value is a string
}

Once you have defined the IndexSignature, adjustments need to be made within your codebase. Below is an example of how you can modify a function utilizing the IndexSignature:

sanitize function(obj: IndexSignature, ...allowed: string[]) {
    const sanitizedObject = {} as IndexSignature;
    Object.keys(obj).forEach((el: string) => {
      if (allowed.includes(el)) {
        sanitizedObject[el] = obj[el];
      }
    });
  }

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

What steps should I take to ensure that this test covers all possible scenarios?

I recently started learning React development and am currently exploring testing with Jest and React Testing Library (RTL). However, I'm facing challenges in achieving complete test coverage for the component code below: import { CustomCardActions, ...

"Exploring the process of extracting data from a JSON URL using NextJS, TypeScript, and presenting the

After tirelessly searching for a solution, I found myself unable to reach a concrete conclusion. I was able to import { useRouter } from next/router and successfully parse a local JSON file, but my goal is to parse a JSON object from a URL. One example of ...

Error: No 'map' property found in 'TwitterserviceService' type

Currently, I am in the process of learning how to develop simple and basic Angular applications. As part of my learning journey, I decided to incorporate my Twitter timeline into one of my projects. To aid me in this endeavor, I referred to various online ...

Angular 8: How to Retrieve Query Parameters from Request URL

Can I retrieve the GET URL Query String Parameters from a specific URL using my Angular Service? For example, let's say I have a URL = "http:localhost/?id=123&name=abc"; or URL = ""; // in my service.ts public myFunction(): Observale<any> ...

Having trouble accessing props on children in TypeScript while using React.Children.toArray?

When using React.Children.toArray in Typescript, the props object on children is not detected. In order to address this issue, I am currently using any[] instead of ReactChild[], as props are not recognized on a array item when using the latter. Can someon ...

Utilizing span elements to display error messages

Currently, I am using a directive on a field to prevent users from entering HTML tags and JavaScript events. However, I am encountering a few challenges: a) My goal is to display an error message immediately when a user tries to input HTML tags or JavaScr ...

The process of incorporating user properties into the output of a Service Bus topic from a Javascript Azure Function

I'm currently developing a TypeScript Azure Function that utilizes an Azure Service Bus topic as its output. Although I am able to send messages successfully, I have encountered difficulties in setting custom metadata properties for the message. In m ...

Issue encountered in Typescript: callback functions are returning undefined value when called from a superclass

As a newcomer to TypeScript and Node.js, I decided to dive into something new by exploring Angular, Node, and Express. While attempting to practice good project structure practices in Express by breaking it down into smaller parts, I encountered an issue. ...

Steer clear of mentioning unbound methods, as they can lead to accidental scoping errors with 'this' when invoking static methods

I've been working on a method map based on a query from the Stack Overflow post linked here to assist me in dynamically calling a static method. But, I keep encountering this error message: Avoid referencing unbound methods that could lead to uninte ...

Having trouble with the Angular Material component? The element 'mat-option' is not recognized

I am having trouble with implementing an Angular Material component. The component is not functioning properly, and I received the following error message: Uncaught Error: Template parse errors: 'mat-option' is not a known element: // ... I sus ...

Creating a conditional class property requirement in TypeScriptAnother way to implement conditionally required class

I am currently in the process of creating an Event class with a data property that is typed based on the type of the event. Here is the code snippet I have been working on: export interface EventTypes { localeChange: { locale: string; }; translat ...

Creating a map in Typescript initialized with a JSON object

In my Typescript class, there is a map that I'm trying to initialize: public map:Map<string,string>; constructor() { let jsonString = { "peureo" : "dsdlsdksd" }; this.map = jsonString; } The issue I'm encounte ...

I am having trouble with the Primeng password template suggestions not appearing as expected

The demonstration available at this link is not functioning correctly, unlike the example provided in the documentation at this website. In the StackBlitz demo, the suggestions are not being displayed as expected for the password template. Take a look at ...

Creating rectangular shapes on the canvas with the help of react hooks

I have a React+Typescript web application and I am currently working on implementing the functionality to draw rectangles on a canvas. My goal is to utilize React hooks instead of classes in order to achieve this. The desired outcome is to enable the user ...

Need help in NestJS with returning a buffer to a streamable file? I encountered an error stating that a string is not assignable to a buffer parameter. Can anyone provide guidance on resolving this issue?

The issue description: I am having trouble returning a StreamableFile from a buffer. I have attempted to use buffer.from, but it does not seem to work, resulting in the error message below. Concern in French language: Aucune surcharge ne correspond à cet ...

The quantity of documents queried does not align with the number of data counts retrieved from Firestore

Facing an issue with calculating the Firestore read count as it keeps increasing rapidly even with only around 15 user documents. The count surges by 100 with each page reload and sometimes increases on its own without any action from me. Could this be due ...

Having trouble with my Angular application, seems to be stuck at the loading screen. Not sure what's causing it, possibly

Hey there, I'm hoping to create a straightforward app that showcases posts. However, I've encountered an issue when deploying the initial page which is stuck on "Loading...". I believe it's a minor problem and would appreciate your assistan ...

Angular version 8.2 combined with Firebase can result in errors such as those found in the `./src/app/app.module.ngfactory.js` file towards the end of the process when attempting to build with

My first time posing a query on this platform, and certainly not my last. The issue at hand involves the ng-build --prod process failing to complete and throwing errors in my Angular 8.2.14 application. I've integrated Firebase into my project succes ...

React development: How to define functional components with props as an array but have them recognized as an object

While trying to render <MyComponent {...docs} />, I encountered the following error: TypeError: docs.map is not a function Here's how I am rendering <MyComponent /> from a parent component based on a class: import * as React from &apo ...

Tips on implementing mongoose 'Query<any>' types

I have been exploring ways to incorporate a cache layer into my TypeScript project. Recently, I came across an insightful article on Medium titled How to add a Redis cache layer to Mongoose in Node.js The author demonstrates adding a caching function to m ...