typescript - Rent sätt att mappa objekt till andra objekt?


Finns det ett bra sätt att mappa objekt till andra objekt? Biblioteksrekommendationer tas också emot.

Till exempel, säg att jag har dessa klasser:

export class Draft {
    id: number;
    name: string;
    summary: string;
}

export class Book {
    id: number;
    name: string;
    info: Info;
}

export class Info {
    value: string;
}

Traditionellt, för att mappa fält från Draft till Book skulle jag behöva göra det manuellt för varje fält:

export class Book {
    [...]

    fromDraft(Draft draft) {
        this.id = draft.id;
        this.name = draft.name;
        this.info = new Info();
        this.info.value = draft.summary;
    }
}

Finns det ett enklare sätt att mappa objektfält som har samma namn? Till exempel Draft och Book's id och name-fält, samtidigt som man också kan definiera egna mappningar, som från draft.summary till book.info.value.

Observera att detta är långt ifrån mitt faktiska användningsfall. Här är det inte så illa att göra tilldelningar manuellt, men för objekt med många liknande namngivna fält är det ganska jobbigt.

Tack!

Svar #1

När det gäller att kopiera egenskaper med samma namn kan du använda Object.assign:

fromDraft(Draft draft) {
    Object.assign(this, draft);
    this.info = new Info();
    this.info.value = draft.summary;
}

Problemet är att det också kommer att skapa this.summary, men det är ett bekvämt sätt att kopiera egenskaper, så om du kan modellera dina klasser på ett annat sätt kan du använda det.

Ett annat alternativ är att ha en lista med gemensamma egenskapsnamn och sedan iterera över den:

const SHARED_NAMES = ["id", "name"];

fromDraft(Draft draft) {
    SHARED_NAMES.forEach(name => this[name] = draft[name]);
    this.info = new Info();
    this.info.value = draft.summary;
}

Svar #2

Oavsett TypeScript kan du använda lodash _.mergeWith och skicka din merge-funktion.

Fördel: Mer generisk (Om du har mer logik kan du lägga till den (till exempel för komplexa typer))

Nackdel: Du behöver lodash

Något som:

var a = {
  foo: [1, 2, 3],
  bar: true
}

var b = {
  foo: [4, 5, 6, 7],
  bar: false
}

var c = _.mergeWith(a, b, function(a, b) {
  if (a.concat) {
    return a.concat(b);
  }
  else {
    return b;
  }
})

console.log('c', c);
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>

http://jsbin.com/xugujon/edit?html,js

Relaterade artiklar