piotrwitek / utility-types

Collection of utility types, complementing TypeScript built-in mapped types and aliases (think "lodash" for static types).
MIT License
5.54k stars 230 forks source link

Add a type "Swap<T, Replaced, Replacing> #176

Open euberdeveloper opened 2 years ago

euberdeveloper commented 2 years ago

Is your feature request related to a real problem or use-case?

If an API returns an object with some dates, such as

interface Resource {
     id: string;
    value: number;
    created: Date;
}

The date will become a string due to json conversion:

interface ResourceReturned {
     id: string;
    value: number;
    created: string;
}

I want a type such that:

type ResourceReturned = Swap<Resource, Date, string>;

Describe a solution including usage in code example

A solution could be

export type Swap<Interface, ReplacedType, ReplacingType> = {
    [k in keyof Interface]: Interface[k] extends ReplacedType ? ReplacingType : Interface[k];
};

But note that it does not support deep, so it should be perfectionated.

Who does this impact? Who is this for?

Everyone that has my problem

Describe alternatives you've considered (optional)

Additional context (optional)

ashatyk commented 2 years ago

I worked on such problem and my idea is:

type _Update<T, U, S> = {
    0: Exclude<U, T> extends T ? (Exclude<T, U> | S) : T,
    1: S
}[[T] extends [U] ? [U] extends [T] ? 1 : 0 : 0]

type Update<T extends object, U, S> = {
    [K in keyof T]: T[K] extends object ? Update<T[K], U, S> : _Update<T[K], U, S>
}

type a1 = {
    b1: symbol | string | number
    b2: symbol | string
    b3: symbol
    b4: string
    b5: {
        c1: 'c1'
        c2: number
        c3: number | symbol
    }
}

type test = Update<a1,symbol, boolean>