• Skip to main content
  • Skip to search
  • Skip to select language
  • Sign up for free
  • Remember language
  • Português (do Brasil)

Object.assign()

Baseline widely available.

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015 .

  • See full compatibility
  • Report feedback

The Object.assign() static method copies all enumerable own properties from one or more source objects to a target object . It returns the modified target object.

The target object — what to apply the sources' properties to, which is returned after it is modified.

The source object(s) — objects containing the properties you want to apply.

Return value

The target object.

Description

Properties in the target object are overwritten by properties in the sources if they have the same key . Later sources' properties overwrite earlier ones.

The Object.assign() method only copies enumerable and own properties from a source object to a target object. It uses [[Get]] on the source and [[Set]] on the target, so it will invoke getters and setters . Therefore it assigns properties, versus copying or defining new properties. This may make it unsuitable for merging new properties into a prototype if the merge sources contain getters.

For copying property definitions (including their enumerability) into prototypes, use Object.getOwnPropertyDescriptor() and Object.defineProperty() instead.

Both String and Symbol properties are copied.

In case of an error, for example if a property is non-writable, a TypeError is raised, and the target object is changed if any properties are added before the error is raised.

Note: Object.assign() does not throw on null or undefined sources.

Cloning an object

Warning for deep clone.

For deep cloning , we need to use alternatives like structuredClone() , because Object.assign() copies property values.

If the source value is a reference to an object, it only copies the reference value.

Merging objects

Merging objects with same properties.

The properties are overwritten by other objects that have the same properties later in the parameters order.

Copying symbol-typed properties

Properties on the prototype chain and non-enumerable properties cannot be copied, primitives will be wrapped to objects, exceptions will interrupt the ongoing copying task, copying accessors, specifications, browser compatibility.

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

  • Polyfill of Object.assign in core-js
  • Object.defineProperties()
  • Enumerability and ownership of properties
  • Spread in object literals

Advisory boards aren’t only for executives. Join the LogRocket Content Advisory Board today →

LogRocket blog logo

  • Product Management
  • Solve User-Reported Issues
  • Find Issues Faster
  • Optimize Conversion and Adoption
  • Start Monitoring for Free

How to dynamically assign properties to an object in TypeScript

' src=

Editor’s note: This article was updated by Yan Sun on 1 October 2024 to cover recent improvements to index access handling in TypeScript 5.5.

How To Dynamically Assign Properties To An Object In TypeScript

Dynamic property assignment is the ability to add properties to an object as needed, rather than defining them upfront. This is useful when properties are conditionally assigned in different parts of the code.

In TypeScript, we can dynamically assign properties to an object using the following methods:

  • Explicitly declaring object type : Explicitly typing objects at declaration time is the simplest approach, but it might not be feasible when properties need to be added dynamically
  • Using object index signature : This allows us to define the type of keys and value, and assign dynamic properties in an object
  • Using the Record utility type : With the Record type, we can create an object type with specified keys and values, as in Record<string, string> , where both the keys and values are of type string
  • Using the Map data type : Using a Map object allows dynamic property assignment, although it lacks strong typing
  • Using optional object property : By declaring an optional property during object initialization like {name?: string} , we can enable dynamic assignment
  • Leveraging type assertions : Type assertions in TypeScript override inferred types, allowing dynamic property assignment without type enforcement
  • Using the Partial utility type : The Partial utility type makes all properties of a type optional, allowing us to initialize an object with any combination of the properties

In this article, we will explore how to benefit from both JavaScript’s dynamism and TypeScript’s type safety, particularly when working with dynamic property assignments.

Consider the following example code:

This seemingly harmless piece of code throws a TypeScript error when dynamically assigning the name property to the organization object:

An Error Is Thrown When Dynamically Assigning A Property To An Object

See this example in the TypeScript Playground .

The source of confusion, perhaps rightly justified if you’re a TypeScript beginner, is: how could something so simple be such a problem in TypeScript?

In short, if we can’t define the variable type at declaration time, we can use the Record utility type or an object index signature to solve this. But in this article, we’ll work through the problem itself and toward a solution that should work in most cases.

The problem with dynamically assigning properties to objects

Generally speaking, TypeScript determines the type of a variable when it is declared. This determined type stays the same throughout our application. There are exceptions to this rule, such as when considering type narrowing or working with the any type, but otherwise, this is a general rule to remember.

In the earlier example, the organization object is declared as follows:

No explicit type is assigned to this variable, so TypeScript infers a type of organization based on the declaration to be {} , i.e., the literal empty object.

If we add a type alias, we can explore the type of organization :

Exploring The Literal Object Type

See this in the TypeScript Playground .

Then, if we try to reference the name prop on this empty object literal:

We will receive the following error:

There are many ways to solve the TypeScript error here. Let’s consider the following:

Solution 1: Explicitly declare the object type

This is the easiest solution to reason through. At the time we declare the object, go ahead and type it, and assign all the relevant values:

This approach eliminates any surprises. By clearly stating what this object type is and declaring all relevant properties upfront, we ensure clarity and avoid unexpected behavior.

However, this is not always feasible if the object properties must be added dynamically, which is why we’re here.

Solution 2: Use object index signature

Occasionally, the properties of the object need to be added at a time after they’ve been declared. In this case, we can use the object index signature as follows:

In the example, we explicitly type the organization variable to the following: {[key: string] : string} , which allows this type to have properties with any string key and string value.

We might be used to object types having fixed property types:

However, we can also substitute the name property for a “variable type.” For example, if we want to define any string property on obj :

Note that the syntax is similar to how we’d use a variable object property in standard JavaScript:

The TypeScript equivalent is called an object index signature.

Moreover, note that we could type key with other primitive types such as string , number , symbol , or literal types:

Nested index signature

We can use nested indexed signatures to represent complex data structures. It allows us to handle dynamic properties in a nested structure:

Here, the Org type represents a data structure with properties with string keys, and each property can also be an object with string keys and string values.

We can go one step further to define a type with deeply nested index signatures. The example below demonstrates the ability to assign dynamic properties to deeply nested objects:

See the TypeScript playground.

Index signature with mapping types

Sometimes, a limited set of properties is known upfront. We can use the index signature and mapping types to create objects with properties named after union types:

The above example defines a type Org with keys based on a union of department names. The OrgHierachy type uses the Partial utility type to make all the properties optional, giving us the flexibility to not assign all the departments.

property object assignment

Over 200k developers use LogRocket to create better digital experiences

property object assignment

Solution 3: Use the Record utility type

The Record utility type allows us to construct an object type whose properties are Keys and property values are Type . It has the following signature: Record<Keys, Type> .

In our example, Keys represents the string type. The solution here is shown below:

Instead of using a type alias, we can also use an inline type:

Using The Record Utility Type

Solution 4: Use the Map data type

A Map object is a fundamentally different data structure from an object , but for completeness, we could eliminate this problem using Map .

Consider the starting example rewritten to use a Map object:

With Map objects, we’ll have no errors when dynamically assigning properties to the object:

Dark Background Typescript Playground Showing Map Object No Errors

This seems like a great solution initially, but the caveat is that the Map object is weakly typed. We can access a nonexisting property and get no warnings at all:

See the TypeScript Playground .

Unlike the standard object, an initialized Map has the key and value types as any — i.e., new () => Map<any, any> . Consequently, the return type of the s variable will be any :

Dark Background Typescript Playground Showing Constant S With Type Any Indicated By Red Arrow

When using Map , at the very least, I recommend passing some type of information upon creation. For example:

The variable s will still be undefined, but we won’t be surprised by its code usage. We’ll now receive the appropriate type for it:

Dark Background Typescript Playground Showing Properly Typed Map Value With Const S With Type String Undefined Indicated By Red Arrow

If we truly don’t know what the keys of the Map will be, we can go ahead and represent this at the type level:

Similarly, if we’re not sure what the keys or values are, be safe by representing this at the type level:

Solution 5: Use the optional object property

While not always feasible, if we know the specific property to be dynamically assigned, we can declare it as an optional property during object initialization as shown below:

If you don’t like the idea of using optional properties, you can be more explicit with the typing:

Solution 6: Leveraging type assertions

TypeScript type assertion is a mechanism that tells the compiler the variable’s type and overrides what it infers from the declaration or assignment. With this, we are telling the compiler to trust our understanding of the type because there will be no type verification.

We can perform a type assertion by either using the <> brackets or the as keyword. This is particularly helpful with the dynamic property assignment because it allows the properties we want for our object to be dynamically set. After all, TypeScript won’t enforce them.

Let’s take a look at applying type assertions to our example:

Dark Background Typescript Playground Showing Dynamic Property Assignment Using Type Assertion

Note that, with type assertions, the compiler trusts that we will enforce the type we have asserted. This means if we don’t, for example, set a value for organization.name , it will throw an error at runtime that we will have to handle ourselves.

Solution 7: Use the Partial utility type

TypeScript provides several utility types that can be used to manipulate types. These utility types include Partial , Omit , Required , and Pick .

We will focus specifically on the Partial utility type for dynamic property assignments. The Partial utility type takes a defined type and makes all of its properties optional. Thus, we can initialize our object with any combination of its properties, from none to all, as each one is optional:

In our example, we defined our organization object as the type partial Org , which means we can choose not to set a phoneNumber property:

Dark Background Typescript Playground Showing Dynamic Property Assignment Using Utility Type Partial

Comparing approaches for dynamic property assignment in TypeScript

In this article, we explored the different options for setting properties dynamically in TypeScript. These options can be grouped by their similarities.

Index/Key signatures

This group of options allows us to define the type of keys allowed without limiting what possible keys can exist. The options in this group include:

  • Using an object index signature
  • Using the Record utility type
  • Using the Map data type (with key/value typing)

With these approaches, we can define the string type for the object key and decide what types to support as values, like String , Number , Boolean , or Any :

See in TypeScript Playground .

Pro: The main benefit of these methods is the ability to dynamically add properties to an object while setting expectations for the possible types of keys and values.

Con: The main disadvantage of this way is that we can’t predict what keys our objects will have, so some references may or may not be defined. An additional disadvantage is that if we decide to define our key signature with type Any , then the object becomes even more unpredictable.

Conditional/Optional properties

This set of object assignment methods shares a common feature: the definition of optional properties. This means the range of possible properties are known but some may not be set. The options in this group include:

  • Using optional object properties
  • Using the Partial utility type
  • Using type assertions

See this example in the TypeScript Playground , or the code block below:

Note: While these options mean that the possible keys are known and may not be set, TypeScript’s compiler won’t validate undefined states when using type assertions. This can lead to unhandled exceptions during runtime. For example, with optional properties and the Partial utility type, name has type string or undefined . Meanwhile, with type assertions, name has type string .

Pro: The advantage of this group of options is that all possible object keys and values are known.

Con: The disadvantage is that while the possible keys are known, we don’t know if they have been set and will have to handle the possibility that they are undefined.

When working with dynamic object properties (especially for using optional properties), type guards can be useful for ensuring type safety and preventing runtime errors. Type guards are a powerful TypeScript feature that allows us to check a variable’s type at runtime and conditionally execute code based on the result.

Recent improvements to index access handling in TypeScript

In TypeScript 5.5, a new improvement called “Control Flow Narrowing for Constant Indexed Accesses” was introduced.

This improvement narrows expressions of the form obj[key] when both obj and key are effectively constant. For example, prior to 5.5, TypeScript would throw an error with the following code. Now, TypeScript can determine that obj[key] is a string after the typeof check, improving type safety and flexibility in similar scenarios:

See in TypeScript playground.

In this article, we explored several ways to dynamically assign properties to TypeScript objects while maintaining type safety. Key approaches include using:

  • Object index signatures
  • The Record utility type
  • The Map data type
  • Optional object properties
  • Type assertions
  • The Partial utility type

Each method offers flexibility in managing dynamic properties while adhering to TypeScript’s strong typing system. Choosing the right approach depends on the use case, whether you prioritize key predictability or type safety.

If you’d like to read more on this subject, please check out my cheatsheet on the seven most-asked TypeScript questions on Stack Overflow, or tweet me any questions . Cheers!

LogRocket : Full visibility into your web and mobile apps

LogRocket Dashboard Free Trial Banner

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.

Try it for free .

Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • #typescript

Would you be interested in joining LogRocket's developer community?

Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.

property object assignment

Stop guessing about your digital experience with LogRocket

Recent posts:.

Vue logo over a brown background.

A guide to two-way binding in Vue

Learn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.

' src=

Drizzle vs. Prisma: Which ORM is best for your project?

Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.

' src=

Practical implementation of the Rule of Least Power for developers

It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.

' src=

Handling memory leaks in Rust

Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.

' src=

3 Replies to "How to dynamically assign properties to an object in TypeScript"

I know this is explicitly for TypeScript, and I think type declarations should always be first. But in general, you can also use a Map object. If it’s really meant to by dynamic, might as well utilize the power of Map.

Great suggestion (updated the article). It’s worth mentioning the weak typing you get by default i.e., with respect to Typescript.

Hi, thanks for your valuable article please consider ‘keyof type’ in TypeScript, and add this useful solution if you are happy have nice time

Leave a Reply Cancel reply

IMAGES

  1. Object Property Assignment in JavaScript, Codecademy's Learn JavaScript

    property object assignment

  2. 3D Object Properties Poster (creat de profesori)

    property object assignment

  3. Property Assignment formatting

    property object assignment

  4. Properties of Objects 1669132

    property object assignment

  5. Class, Property, Object, Method

    property object assignment

  6. The five key attributes of a Property Object

    property object assignment

VIDEO

  1. OBJECT ORIENTED PROGRAMMING IN SYSTEM VERILOG PART

  2. #20. Assignment Operators in Java

  3. Use Destructuring Assignment to Pass an Object as a Function's Parameters (ES6) freeCodeCamp

  4. Awesome CSS Property

  5. Intellectual Property

  6. How To Set A JS object property name from a variable