Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: How to map object to type?

Assume that I have an object containing some data. I want to build a generic mapper (only a function respectively - I don't want to instantiate a new class all the time) for all types to use like this: this.responseMapper.map<CommentDTO>(data);

It should simply take all properties from the given type and map the data to it. What I tried so far:

public map<T>(values: any): T {
    const instance = new T();

    return Object.keys(instance).reduce((acc, key) => {
        acc[key] = values[key];
        return acc;
    }, {}) as T;
}

new T(); will throw an error: 'T' only refers to a type, but is being used as a value here.

What's the correct way to do this?

like image 728
sandrooco Avatar asked Jan 09 '18 10:01

sandrooco


People also ask

How do you give an object a key to type?

Use the keyof typeof syntax to create a type from an object's keys, e.g. type Keys = keyof typeof person . The keyof typeof syntax returns a type that represents all of the object's keys as strings.

How do you type a Map on TypeScript?

Use Map type and new keyword to create a map in TypeScript. let myMap = new Map<string, number>(); To create a Map with initial key-value pairs, pass the key-value pairs as an array to the Map constructor.

How do you define object of objects type in TypeScript?

To define an object of objects type in TypeScript, we can use index signatures with the type set to the type for the value object. const data: { [name: string]: DataModel } = { //... }; to create a data variable of type { [name: string]: DataModel } where DataModel is an object type.


1 Answers

You need to pass the type constructor to the method. Typescript erases generics at runtime to T is not known at runtime. Also I would tighten values a bti to only allow memebers of T to be passed in. This can be done with Partial<T>

public map<T>(values: Partial<T>, ctor: new () => T): T {
    const instance = new ctor();

    return Object.keys(instance).reduce((acc, key) => {
        acc[key] = values[key];
        return acc;
    }, {}) as T;
 }

Usage:

class Data {
    x: number = 0; // If we don't initialize the function will not work as keys will not return x
}

mapper.map({ x: 0 }, Data)
like image 70
Titian Cernicova-Dragomir Avatar answered Oct 20 '22 19:10

Titian Cernicova-Dragomir