Techniques for updating the names of interface keys?

One task involves renaming keys within an interface while accounting for variations in nesting levels. Consider the following example:

interface Foo {
  _id: string
  nested: {
    _id: string
    nested: {
      _id: number
    }
  }
}

// How can a new type be created to match the structure below?

type Bar = {
  id: string
  nested: {
    id: string,
    nested: {
      id: number
    }
  }
}

In this scenario, the goal is to change all instances of _id to id, while keeping the type unchanged.

Answer №1

Give this type a try:

// Define the PickRename type that renames keys in an object

type PickRename<T, K extends string, R extends string> =
  T extends object ? K extends keyof T ?
  ({ [P in R]: PickRename<T[K], K, R> } &
    { [P in Exclude<keyof T, K>]: PickRename<T[P], K, R> }) extends infer I ?
  { [PP in keyof I]: I[PP] } : never
  : T
  : T

Explanation with an example:

  1. If T is an object and key K (for instance, "_id") exists, process the object by changing the key names.

  2. Remove the existing key K and replace it with the new name R; recursively update each property as needed.

  3. The syntax

    extends infer I ? { [PP in keyof I]: I[PP] } : never 
    is for clarity and readability of the intersected types.

/*
type T1 = {
    id: string;
    nested: {
        id: string;
        nested: {
            id: number;
        };
    };
}
*/
type T1 = PickRename<Foo, "_id", "id">

To alter multiple properties at once, explore different PickRename implementations here.

Dive into the TypeScript playground here.

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

The React Functional Component undergoes exponential re-renders when there is a change in the array

I'm encountering a problem with one of my functional components. Essentially, it maintains an array of messages in the state; when a new message is received from the server, the state should update by adding that new message to the array. The issue ar ...

The property 'name' is not found within the type 'FormGroup'

I am encountering an issue with form validation in my Angular app using ReactiveForms. The error message reads as follows: Error: src/app/pages/contact/contact.component.ts(48,32): error TS2339: Property 'assunto' does not exist on type &a ...

Searching for values within an array of objects by iterating through nested arrays to apply a filter

Having trouble returning the testcaseid from an array to this.filteredArray Able to fetch header value and all values of the array when the search word is empty. Seeking assistance with iterating through the testcaseid and header on the search input fiel ...

Ways to expand the inheritance of a family's assets in the next generation

I am facing an issue with the following code snippet: class Table { get pagination () { return { get item () { return { log (s : string) { console.log(s); ...

Deduce the generic types of child components based on the type of the

In my quest to develop a table component that utilizes components to define columns, I came up with the following structure: interface UsageModel { title: string; } const Usage = () => { const data: UsageModel[] = [{ title: "Stack Overflow&qu ...

Tips for effectively utilizing the Angular ngIf directive for toggling the visibility of elements

<div *ngFor = "let element of myElements, let i=index" [ngClass]="{'selected':element[i] == i}"> <li> Name: {{element.element.name}}</li> <li> Description: {{element.element.description}}</li ...

The TypeScript compiler remains silent when a declaration is missing

Encountered an unusual issue in my NodeJS project that I need help with. I suspect there is a simple solution hidden in tsconfig.json. Currently, I am working with TypeScript v1.7.3. The file test1.ts includes a variable declaration: // test1.ts let a = ...

Using Typescript to set a custom timeout duration based on a dynamic variable within a for loop

My function includes a timeout that changes every 3 seconds: setActiveImage(promotions) { for (let i = 0; i <= promotions.length - 1; i++) { setTimeout(()=> { this.activeImage = 'http://myrul/public/Commercials/' + promo ...

Opening and closing a default Bootstrap modal in Angular 2

Instead of using angular2-bootstrap or ng2-bs3-modal as recommended in the discussions on Angular 2 Bootstrap Modal and Angular 2.0 and Modal Dialog, I want to explore other options. I understand how the Bootstrap modal opens and closes: The display pro ...

Dealing with reactive form controls using HTML select elements

I am working with a template that looks like this: <form [formGroup]="form"> <mdl-textfield type="text" #userFirstName name="lastName" label="{{'FIRSTNAME' | translate}}" pattern="[A-Z,a-zéè]*" error-msg ...

Adding jQuery and other libraries to Typescript for optimal functionality

After spending days researching and struggling, I am reaching out here for clarification on the process of importing a library in Typescript. I used to just add the script tag and everything would work fine. Now that I am working on building a MEAN-Stack ...

The combination of TypeScript decorators and Reflect metadata is a powerful tool for

Utilizing the property decorator Field, which adds its key to a fields Reflect metadata property: export function Field(): PropertyDecorator { return (target, key) => { const fields = Reflect.getMetadata('fields', target) || []; ...

Is there a way to identify the specific button that was clicked within an Angular Material dialog?

import {Component, Inject} from '@angular/core'; import {MdDialog, MdDialogRef, MD_DIALOG_DATA} from '@angular/material'; /** * @title Dialog Overview Example with Angular Material */ @Component({ selector: 'dialog-overview-ex ...

An unexpected problem in Mongoose and Typescript

I encountered an issue while trying to update some data within my main interface. The problem arises when I attempt to update the data and receive an error mentioning that .save() is not defined. To address this issue, I created another interface to exten ...

Issue with Component in Angular not functioning properly with proxy construct trap

Currently working with Angular 17, I have a straightforward decorator that wraps the target with Proxy and a basic Angular component: function proxyDecorator(target: any) { return new Proxy(target, { construct(target: any, argArray: any[], newTarget: ...

Ways to specify an unused parameter within a function

As I work on my code, I encounter the need to separate the key and value from a request params object in order to validate the value using ObjectID. To achieve this, I decided to iterate over an array of entries and destructure the key and value for testin ...

Error: Unable to initialize i18next as a function

For my current project, I am utilizing TypeScript and i18next for internalization. TypeScript version: 2.1.4 i18next version: 2.3.4 @types/i18next version: 2.3.35 In the specific file: import * as i18next from 'i18next'; i18next.init({ ...

Problem of Restricting Array to Single Element at Once

I seem to be facing an issue with a seemingly straightforward function that creates an array - and I'm unable to pinpoint the root cause of the problem. It's probably something simple, but for some reason, it eludes me. Here is the function in q ...

Attempting to clear the value of a state property using the delete method is proving to be ineffective

Within my React-component, there exists an optional property. Depending on whether this property is set or not, a modal dialog is displayed. Therefore, when the modal should be closed/hidden, the property must not be set. My state (in simplified form): i ...

Dispatching an asynchronous function error in React with TypeScript and Redux - the parameter type is not assignable to AnyAction

Currently, I am in the process of developing a web application that utilizes Firebase as its database, along with Redux and TypeScript for state management. Within my code, I have a dispatch function nested inside a callback function like so: export const ...