Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert interface to mapped type in Typescript

Tags:

Background

In the typescript documentation for mapped types the following example is given:

type Proxy<T> = {
    get(): T;
    set(value: T): void;
}

type Proxify<T> = {
    [P in keyof T]: Proxy<T[P]>;
}

function proxify<T>(o: T): Proxify<T> {
    // ... wrap proxies ...
}

let proxyProps = proxify(props);

It is unclear to me how I would write the proxify function.

What I need it for

I have the following types

interface User extends BaseRecord {
    readonly 'id': number;
    readonly 'name'?: string;
}

interface FormField<T> {
    readonly value: T;
    readonly edited: boolean;
}

type WrappedInFormField<T> = {
    [P in keyof T]: FormField<T[P]>;
};

And I need to write a function with the following signature

const wrap = <T>(o: T): WrappedInFormField<T> => {
    // ...What goes here?...
}

wrappedUser: WrappedInFormField<User> = wrap<User>(UserIJustGotFromApi);

How can I do that?

like image 650
Christian Ravn Avatar asked Mar 19 '18 13:03

Christian Ravn


1 Answers

You need to just build up the object. Typescript will offer no help in creating mapped types, you just build them up as you normally would in Javascript.

const wrap = <T>(o: T): WrappedInFormField<T> => {
    // Create an empty object that we will add the properties to, assert it will be a WrappedInFormField<T> once we are done with it
    let result = {} as WrappedInFormField<T>;
    // Get all the keys of the original object
    for(var key in Object.keys(o)) { 
        // Create something compatible with FormField
        // You could instantiate a class, but you will not have access to the type of each property,
        // you could use any instead (for example if FormField<T> is a class you could just call new FormField<any> since types are erased it will not really matter)
        result[key] = {
            value: o[key],
            edited: false
        };
    }
    // return the result
    return  result;
}
like image 107
Titian Cernicova-Dragomir Avatar answered Sep 23 '22 12:09

Titian Cernicova-Dragomir