In JavaScript is de Spread-operator (...) geïntroduceerd voor het gemak van het kopiëren en uitbreiden van objecten, met arrays werd het al lang gebruikt, en sinds ES2018 ook met objecten. In TypeScript is de Spread niet alleen een syntactische verbetering, maar ook een hulpmiddel voor nauwkeurige typering bij manipulaties met objecten.
Historisch gezien werd cloneren of uitbreiden van een object in JavaScript gedaan met Object.assign, maar deze aanpak leidde gemakkelijk tot verlies van type veiligheid en gevaarlijke overlappen van sleutels, vooral als de objectstructuur complex was.
Het probleem is dat bij het gebruik van Spread voor het samenvoegen/uitbreiden van objecten TypeScript een nieuw type afleidt op basis van de invoerstructuren, waarbij mogelijke conflicten van sleutels worden afgehandeld ("de laatste wint"), maar dat is niet altijd wat de ontwikkelaar bedoelde. Speciale aandacht moet worden besteed aan overlappingen met optionele velden, readonly en het bestaan van privé-eigenschappen in klassen.
Oplossing: gebruik Spread en laat de TypeScript-compiler het resultaat automatisch afleiden. Voor complexe gevallen is het belangrijk om de type-ingangen expliciet te beperken en goed te letten op veranderingen in de type structuren.
Voorbeeldcode:
interface User { name: string; age: number; } interface Extra { isAdmin?: boolean; readonly city: string; } const base: User = { name: 'Ivan', age: 28 }; const extended: User & Extra = { ...base, city: 'Moscow', isAdmin: true };
Belangrijke kenmerken:
Kan je met Spread-erfelijkheid een "deep copy" van een object in TypeScript krijgen?
Antwoord: Nee. Spread maakt alleen oppervlakkige kopieën (shallow copy), geneste objecten blijven per referentie.
const original = { user: { name: 'Anna' } }; const cloned = { ...original }; cloned.user.name = 'Maria'; // original.user.name verandert ook
Zal het type verkleinen of uitbreiden bij het Spread van objecten met overlappende sleutels, en hoe heeft dit invloed op de type annotatie van de variabele?
Antwoord: Bij Spread wordt het type van de variabele uitgebreid, en in het geval van overlappende sleutels winnen de eigenschappen aan de rechterkant; als er een expliciete type annotatie is, kan er een fout optreden als de types niet compatibel zijn.
const a = { id: 4, value: "abc" }; const b = { value: 123 }; const c: { id: number; value: number } = { ...a, ...b }; // ok
Kan Spread worden toegepast op klassen en wat gebeurt er met privé-eigenschappen?
Antwoord: Spread is alleen toepasbaar op openbare eigenschappen van de klasse. Privé(private/#) en beschermde protected velden komen niet in het resulterende object.
class Person { private id = 77; name = "Bob"; } const p = new Person(); const spreaded = { ...p }; // spreaded: { name: string }
Een ontwikkelaar doet Spread van waarden van het object settings voor het uitbreiden van gebruikersopties:
const common = { theme: 'light', notifications: true }; const user = { notifications: false, signature: 'Sasha' }; const merged = { ...common, ...user };
Hij verwacht dat merged type-consistent is, maar maakt per ongeluk een fout met het type van het veld signature, zich niet realiserend dat Spread enkel sleutels kopieert en niet hun waarden valideert.
Voordelen:
Nadelen:
Voor het samenvoegen van configuraties wordt Spread alleen gebruikt na validatie en met een type annotatie voor de teruggegeven waarde:
interface Settings { theme: "light" | "dark"; notifications: boolean; signature?: string; } function getSettings(common: Settings, specific: Partial<Settings>): Settings { return { ...common, ...specific }; }
Voordelen:
Nadelen: