A TypeScript type that duplicates the structure of another object type, while modifying the property types based on their original conditions

I am in need of a TypeScript type that can duplicate another object type while adjusting the types of properties based on their original conditions. This adjustment should apply to all nested and deeply nested properties as well.

For instance, consider a type called DateToStrings<T> that converts all properties of type Date into properties of type string. Here is an example:

If we have a class:

class Milk {
  brandName: string,
  price: number,
  dealExpiredAt: Date,
  properties: {
    expirationDetails: {
      expiredAt: Date
    }
  }
}

The resulting type DateToStrings<Milk> would be:

{
  brandName: string,
  price: number,
  dealExpiredAt: string,
  properties: {
    expirationDetails: {
      expiredAt: string
    }
  }
}

I could really use some guidance on how to tackle this problem. Any tips or suggestions for existing types/packages that might accomplish something similar?

Answer №1

To tackle this problem, you can utilize recursive conditional types. While not covering all edge cases, the following code snippet should be sufficient for the example provided:

type DateToStrings<T> = {
    [K in keyof T]: T[K] extends Date
    ? string
    : T[K] extends Array<infer I>
    ? Array<DateToStrings<I>>
    : T[K] extends object
    ? DateToStrings<T[K]>
    : T[K]
}

type MilkTransformed = DateToStrings<Milk>

const foo: MilkTransformed = {
    brandName: 'string',
    prince: 123,
    dealExpiredAt: 'Date',
    properties: {
        expirationDetails: {
            // Expected error: Type 'Date' is not assignable to type 'string'
            expiredAt: new Date
        }
    }
}

Try it out on 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

Using TypeScript for Geolocation

Consider the code snippet below: pos:number; getPosition() { navigator.geolocation.getCurrentPosition((position) => { this.pos = position.coords.latitude; During debugging, the value of 'this.pos' is undefined, while 'posi ...

A common method for incorporating personalized react-scripts into create-react-app

After creating a project using create-react-app in TypeScript, I am looking to integrate custom react-scripts without ejecting. What is the most effective approach to achieve this? ...

Issue with readonly is preventing the ability to alter the font color of the input

I need to change the font color of a disabled input. When it is disabled, it appears gray and I want it to be black instead. I attempted to use readonly but that did not have the desired effect, and now the input is showing [object Object]. Below is my HTM ...

What is the best way to obtain a reference to an instance of my Angular 2 directive?

Angular 2 rc 5 was written using typescript 1.9 I am trying to access the instance of my attribute directive. Although I am using ViewChild, which typically works with components, it is giving me a handle to the element containing the directive. template ...

Incorporating Firebase administrator into an Angular 4 project

Currently encountering an issue while trying to integrate firebase-admin into my angular project. Despite my efforts, I am unable to resolve the error that keeps popping up (refer to the screenshot below). https://i.stack.imgur.com/kdCoo.png I attempted ...

Encountered an error while trying to generate the Component class for the ColorlibStepIcon from Material UI in TypeScript

I am trying to convert the ColorlibStepIcon functional component into a class component for my Stepper. Unfortunately, I have not been successful and keep encountering errors. I have attempted some changes but it is still not working as expected. You can ...

Can Vue instances support private computed properties?

Vue is a versatile tool that I utilize for both service classes and components. When it comes to reactive computeds, they prove to be incredibly beneficial. However, I often find myself wanting a clear way to differentiate between public interface compute ...

VS Code is throwing an Error TS7013, while Typescript remains unfazed

In my Typescript/Angular project, I have the following interface: export interface MyInterface { new (helper: MyInterfaceHelpers); } After compiling the project, no errors are shown by the Typescript compiler. However, VSCode highlights it with squiggl ...

What is the most effective way to structure a React function incorporating nested objects and mapping?

As a newcomer to Typescript, I am facing challenges in properly typing the following code snippet. I have experimented with Interfaces and individually typing properties as well, but it seems like I am only scratching the surface and encountering new typin ...

Update current properties of objects

I'm feeling like I'm going crazy and could really use some assistance. My predicament involves a function that looks like this: private generateTimeObject(firstObject: someInterface, secondObject?: someInterface) { let firstTime; let secondTi ...

Is it feasible for the Drawer to be a fixed feature that sits atop the content?

I am looking to have a compact drawer positioned on the left side of my screen, similar to the example shown in the Material UI Documentation: https://i.sstatic.net/W21Kd.png However, I would like it to float over the content (like the variant="temporary ...

how to navigate to a different page programmatically upon selecting an option in the side menu

ionic start mySideMenu sidemenu --v2 After creating a sidemenu using the code above, I implemented some login-logout functionality by storing user details in a localStorage variable named "userDetails". When clicking on the logout option from the sideme ...

Is it possible to utilize tsc --watch exclusively for type checking alongside esbuild?

When I execute tsc --noEmit --incremental, it takes approximately 17 seconds to complete. To improve the speed, tsc provides watch mode which now only takes around 2 seconds. This is my current script: // type checking tsc --noEmit --incremental // build ...

How can one retrieve the "code" attribute from a FirebaseError object in AngularFire using TypeScript?

When using FirebaseError with a "code" property, how can you access it within the catch method of a promise? The code snippet below results in a TypeScript error: Property 'code' does not exist on type 'Error'. this.af.database .object ...

Error message: Custom binding handler failed: 'Flatpickr' is not a valid constructor

Trying my hand at creating a custom binding handler in knockout for Flatpickr has hit a snag. Upon attempting to use it, an error is thrown: Uncaught TypeError: Unable to process binding "datetimepicker: function (){return startDate }" Message: Flatpickr ...

Receive a list of articles based on your subscription status

I am looking to create a filter that can retrieve subscription records Entity 'Subscription' export class Subscription { @PrimaryColumn() id: string; @Column('uuid') userId: string; @Column('uuid') targetUserId: s ...

Creating a stream of observables in RxJs and subscribing to only the latest one after a delay: A comprehensive guide

I am trying to create a stream of Observables with delay and only subscribe to the last one after a specified time. I have three HostListeners in which I want to use to achieve this. I would like to avoid using Observable form event and instead rely on H ...

Designing personalized plugins with Typescript in Nuxt

In my Nuxt project, I have implemented a custom plugin file that contains an object with settings called /helpers/settings: export const settings = { baseURL: 'https://my-site.com', ... }; This file is then imported and registered in /plugi ...

Why has request.query changed from 'any' in Express? TypeScript error with request.query types

Upon running npm i, I encountered an error when trying to pass query parameters to a function that expects a string: Argument of type 'string | Query | (string | Query)[]' is not assignable to parameter of type 'string'. Type 'Quer ...

Having trouble converting TypeScript to JavaScript, and encountering difficulty locating the 'protractor' module

I'm facing an issue with compiling TypeScript to JavaScript because I can't find the module 'protractor'. Despite having Protractor, TypeScript, and Jasmine installed locally with their respective types. Here is the structure of my pro ...