Wie kombiniere ich Objekteigenschaften in Typoskript?

82

Ich würde gerne wissen, wie das am besten geht, wenn ich zwei Objekte habe

var objectA = {
    propertyA: 1,
    propertyB: 2
    ...
    propertyM: 13
}

var objectB = {
    propertyN: 14,
    propertyO: 15
    ...
    propertyZ: 26
}

Wenn objectC von erstellt wird

var objectC = Object.assign(objectA, objectB);

Wie kann ich objectC deklarieren / beschreiben, damit der Compiler / die IDE weiß, dass er die Eigenschaften von objectA und objectB hat?

Ich möchte einen Weg finden, ohne Schnittstellen für objectA und objectB definieren zu müssen. Ich möchte nicht zweimal eine Deklaration und Definition / Bewertung für dieselbe Eigenschaft schreiben. Diese Redundanz ist erheblich, wenn ich zu viele Eigenschaften für ein Objekt habe.

(Gibt es einen Operator, der die Schnittstelle / den Typ eines vorhandenen Objekts extrahieren kann?)

Ist es möglich?

WawaBrother
quelle

Antworten:

155

Scheint so, sollte dies den Trick tun:

var objectA = {
    propertyA: 1,
    propertyB: 2,
    .
    . // more properties here
    .
    propertyM: 13
};

var objectB = {
    propertyN: 14,
    propertyO: 15,
    .
    . // more properties here
    .
    propertyZ: 26
};

var objectC = {...objectA, ...objectB}; // this is the answer

var a = objectC.propertyA;

var n = objectC.propertyN;

Basierend auf diesem Artikel: https://blog.mariusschulz.com/2016/12/23/typescript-2-1-object-rest-and-spread


Außerdem spielt die Reihenfolge der Variablen bei der Zerlegung eine Rolle. Folgendes berücksichtigen:

var objectA = {
    propertyA: 1,
    propertyB: 2, // same property exists in objectB
    propertyC: 3
};

var objectB = {
    propertyX: 'a',
    propertyB: 'b', // same property exists in objectA
    propertyZ: 'c'
};

// objectB will override existing properties, with the same name,
// from the decomposition of objectA
var objectC = {...objectA, ...objectB}; 

// result: 'b'
console.log(objectC.propertyB); 

// objectA will override existing properties, with the same name,
// from the decomposition of objectB
var objectD = {...objectB, ...objectA}; 

// result: '2'
console.log(objectD.propertyB); 
Alkasai
quelle
4
Nur um die Antwort zu verbessern: Diese Zeile macht den Trick: var objectC = {... objectA, ... objectB};
Amirreza
Ich möchte die Eigenschaft von objectA aktualisieren, wenn in beiden Objekten derselbe Schlüssel vorhanden ist. Bedeutet, wenn der Schlüssel derselbe ist, sollte er die Eigenschaft von objectB annehmen. Wie ist es möglich?
Ankur Akvaliya
Lesen Sie die Kommentare in meiner Antwort. Grundsätzlich werden Eigenschaften von links nach rechts erstellt, wobei jede neue Information die vorhandene überschreibt : var objectC = {...objectA, ...objectB};. Das Eigenschaftenformular objectBüberschreibt Eigenschaften, von denen bereits Eigenschaften zugewiesen wurden objectA, wenn die Eigenschaften denselben Namen haben.
Alkasai
Dies funktioniert, daher antwortet OP. Ich befürchte jedoch, dass jetzt kein Typ mit objectD oder objectC verknüpft ist. Wenn Sie versuchen, ihn explizit in etwas einzugeben (vorausgesetzt, es gibt einen solchen Typ), funktioniert er nicht. Gibt es eine typsichere Möglichkeit, dies zu tun?
Srivathsa Harish Venkataramana
@SrivathsaHarishVenkataramana Die Typen werden aus der Zuordnung abgeleitet. Also wird objectC haben propertyB: string, während objectD darauf schließen wird als propertyB: number. Sie können beide C & D: type ABC = { propertyA: number; propertyB: string | number; propertyC: number; propertyX: string; propertyZ: string; }oder nur eine davon manuell eingeben, indem Sie propertyB auf string oder number setzen.
Alkasai
10

Der Compiler / die IDE weiß also, dass sie die Eigenschaften von ObjektA und ObjektB hat.

Verwenden Sie einen Kreuzungstyp + Generika. ZB von hier aus

/**
 * Quick and dirty shallow extend
 */
export function extend<A>(a: A): A;
export function extend<A, B>(a: A, b: B): A & B;
export function extend<A, B, C>(a: A, b: B, c: C): A & B & C;
export function extend<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
export function extend(...args: any[]): any {
    const newObj = {};
    for (const obj of args) {
        for (const key in obj) {
            //copy all the fields
            newObj[key] = obj[key];
        }
    }
    return newObj;
};

Mehr

Beide werden hier erwähnt: https://basarat.gitbooks.io/typescript/content/docs/types/type-system.html

Basarat
quelle
Vielen Dank. Das scheint zu funktionieren. Die Funktion "extens ()" ist jedoch in einer Bibliothek eines Drittanbieters definiert. Gibt es eine Möglichkeit, diese spezifische Definition für "extens ()" in der Datei "d.ts" zu überschreiben? (Ich verwende den Unterstrich _.extend ()).
WawaBrother
Jep. Einfach ändernunderscore.d.ts
Basarat
4

(Gibt es einen Operator, der die Schnittstelle / den Typ eines vorhandenen Objekts extrahieren kann? Ist dies möglich?)

Sie sollten für Typof gehen .

type typeA = typeof objectA;
type typeB = typeof objectB;

Um sie zusammenzuführen, können Sie die Kreuzungsoperation verwenden, wie bereits erwähnt.

type typeC = typeA & typeB
Hav
quelle
4

Verwenden Sie den Typescript-Spread-Operator, den er in Javascript Object.assign () transpiliert.

Wenn Sie das Zusammenführen von Deep Tree-Objekten benötigen, können Sie die Änderungsfunktion des Best-Global- Pakets verwenden

Eugenio
quelle
3

Versuche dies..

const person = { name: 'TRilok', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };

const summary = {...person, ...tools, ...attributes};
Trilok Singh
quelle