Assign a true or false value to every attribute of an object

Imagine we have a scenario with an interface like this:

    interface User {
       Id: number;
       FirstName: string;
       Lastname: string;
       Age: number;
       Type: string;
    }

and a specific method for copying properties based on a flag.

    function copyIfAccepted<T extends object, K extends keyof T>(source: T, dest: T, key: K, 
  isAccepted: boolean) {
      if (isAccepted && source[key] !== dest[key]) {
        dest[key] = source[key];
      }
    }

Currently, the method is being called multiple times for each property. Keep in mind that not all properties are listed here.

     copyIfAccepted(oldUser, newUser, 'Id', true);
     copyIfAccepted(oldUser, newUser, 'FirstName', false);
     copyIfAccepted(oldUser, newUser, 'LastName', true);
     copyIfAccepted(oldUser, newUser, 'Age', true);

Is there a way to refactor this method so it only needs to be called once for all relevant properties? This should be done using TS 4.9

Answer №1

As previously stated in my comment, a helper type can be created to iterate over any type and convert it into an object with its attributes as booleans for the "isActive" part:

interface User {
  Id: number;
  FirstName: string;
  Lastname: string;
  Age: number;
}

type ToBooleanType<T> = {
  [P in keyof T]: boolean;
};

function copyIfAccepted<T extends object>(source: T, dest: T, checks: ToBooleanType<T>) {
  for (const key in source) {
    const sourceValue = source[key];
    const destValue = dest[key];
    const isAccepted = checks[key];

    if (isAccepted && sourceValue !== destValue) {
      dest[key] = sourceValue;
    }
  }
}
const user1: User = { Age: 21, FirstName: 'Joe', Id: 1, Lastname: 'Dirt' };
const user2: User = { Age: 26, FirstName: 'Jane', Id: 3, Lastname: 'Doe' };

copyIfAccepted(user1, user2, { Id: false, Age: true, FirstName: false, Lastname: true });

console.log(user1, user2);

Output:

[LOG]: {
  "Age": 21,
  "FirstName": "Joe",
  "Id": 1,
  "Lastname": "Dirt"
},  {
  "Age": 21,
  "FirstName": "Jane",
  "Id": 3,
  "Lastname": "Dirt"
} 

This code demonstrates that only the checked attributes are copied over if they are different.

Typescript 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

Difficulties with managing button events in a Vue project

Just getting started with Vue and I'm trying to set up a simple callback function for button clicks. The callback is working, but the name of the button that was clicked keeps showing as "undefined." Here's my HTML code: <button class="w ...

Troubleshooting issue of incorporating hintText in a TextField within a create-react-app-with-typescript

After recently downloading, installing, and running the create-react-app-with-typescript, I have been exploring different components. My latest experiment involved adding a TextField with hintText using the following code: import TextField from 'mate ...

How come Typescript claims that X could potentially be undefined within useMemo, even though it has already been defined and cannot be undefined at this stage

I am facing an issue with the following code snippet: const productsWithAddonPrice = useMemo(() => { const addonsPrice = addonsSelected .map(id => { if (addons === undefined) { return 0} return addons.find(addon => addo ...

Discover the latest DOM elements using Webdriverio 5

Currently, I am developing a REact based CMS application that features a form with multiple carousels. I am encountering an issue where the webdriverio implementation is unable to locate an element, even though the same xpath works fine when tested manua ...

Error encountered during conversion to Typescript for select event and default value

When trying to set the defaultValue in a Select component, TSlint throws an error - Type 'string' is not assignable to type 'ChangeEvent<HTMLInputElement> | undefined - for the code snippet below: const App = () => { const [ mont ...

Transform Loopback 4 filter into a SQL WHERE condition

When using Loopback 4, the filter object that is received by functions like Get and Count appears as shown below: { where: { property: { op: value; } } } I am interested in converting this structure into an SQL WHERE clause to use it in ...

Tips on Showing a Unique List in Mat-Table?

Here's what I'm trying to accomplish: I have a list and I want to display it without any duplicates. I attempted using the code (this.model.map(x => x.map), but it resulted in an error. Can anyone help me fix this? model: myModel[]; myObj:any; re ...

fakeAsync failing to synchronize with async task completion

Scenario In my testing process, I am evaluating a component that utilizes an observable-based service to retrieve and display data for internationalization purposes. The i18n service is custom-made to cater to specific requirements. While the component ...

Tips for generating a fixed-length array from multiple arrays with different lengths, focusing on selecting items from each array according to their significance

In order to create a quiz, I am looking to extract 'questions' from various 'topic' arrays. These topics are selected based on the user's preference and are used to populate a question bank for a 20-question quiz. The topics rated ...

Numerous unspecified generic arguments

Imagine a collection of functions, each capable of taking an argument and returning a value (the specifics don't matter): function convertToNumber(input: string): number { return parseInt(input) } function convertToBoolean(input: number): boolean { ...

Issue with VS2017RC: TypeScript fails to produce JavaScript files

After updating to VS 2017, I noticed that modifications made to a typescript file no longer result in the generation of any javascript code, despite receiving a message indicating "outputs generated successfully" on the lower bar. I tested this issue on t ...

Developing a Next.js application using Typescript can become problematic when attempting to build an asynchronous homepage that fetches query string values

Having recently started delving into the world of React, Next.js, and Typescript, I must apologize in advance if my terminology is not entirely accurate... My current learning project involves creating an app to track when songs are performed. Within the ...

Using Angular 2 with the firebase-admin sdk

Whenever I attempt to integrate the firebase-admin SDK into my Angular2 project, an error occurs: ERROR in ./~/firebase-admin/lib/auth/token-generator.js Module not found: Error: Can't resolve 'jsonwebtoken' in '/home/koucky/git_projec ...

TS: How can we determine the type of the returned object based on the argument property?

Assume we have the following data types type ALL = 'AA' | 'BB' | 'CC'; type AA = { a: number; }; type BB = { b: string; }; type CC = { c: boolean; }; type MyArg = { type: ALL }; I attempted to create a mapping between type n ...

Tips for retrieving JSON files within karma tests

I am currently working on developing a test for my TypeScript class that involves retrieving data from a JSON file. readData<T>(filePath: string): Promise<T> { return Qajax.getJSON(filePath); } For testing purposes, I am utilizing the Jas ...

The power of Typescript shines in its ability to ensure type safety when working with conditional

I am struggling with typing a simple function in Typescript that takes a union type and a boolean as parameters. Here is the code snippet: type A = 'a' | 'A'; function f(a: A, b: boolean): string { if (b) { switch (a) { ...

Update the input value with the selected option from the dropdown menu in Angular

How can I dynamically set the value of an input field based on the selection from a dropdown menu in Angular using Reactive Forms? Below is my HTML code: <nb-card> <nb-card-header> Services </nb-card-header> <nb-card-body&g ...

An issue arises following an upgrade in Angular from version 9 to version 10, where the property 'propertyName' is being utilized before it has been initialized

I've spent time looking on Google, Github, and Stackoverflow for a solution to this error, but I'm still struggling to fix it. Can anyone offer a suggestion or help? Recently, I upgraded my Angular project from version 9 to version 10, and after ...

Apply a spread of nested elements onto another spread

I am working with an array containing last names of Persons and need to populate new entries. However, I only have the last names and not the full Person objects. How can I address this issue? type Person = { name: string, lastName: string, age: ...

Potential solution for communication issue between Angular CLI and Flask due to cross-origin error

Initially, the user id and password are submitted from the UI (angular) to Flask: public send_login(user){ console.log(user) return this.http.post(this.apiURL+'/login',JSON.stringify(user),this.httpOptions) .pip ...