How do I dynamically assign properties to an object in TypeScript?
To dynamically assign properties to an object in TypeScript, you typically need one of the following:
- An index signature (e.g.,
[key: string]: any
) so TypeScript knows any string key is allowed. - A mapped type or
Record
type if you know the expected types of the values but need dynamic keys. - Casting the object to
any
(or using a type assertion), though this bypasses type safety.
Below are common approaches in more detail.
1. Using an Index Signature
When you define an index signature, you tell TypeScript “this object can have arbitrary string keys, and the values will be of type X.” For example:
interface StringMap { [key: string]: string; } const myObj: StringMap = {}; myObj["title"] = "Hello"; myObj["description"] = "World!";
- Now
myObj
can have any string key, and the value must be a string. - You can also make the index signature
string | number | boolean
, or a custom type—whatever fits your usage.
Example with Mixed Types
If you need any type for the values:
interface AnyMap { [key: string]: any; } const myObj: AnyMap = {}; myObj["title"] = "Hello"; myObj["count"] = 42; myObj["data"] = { nested: true };
You lose strong typing on the values, but you gain the ability to store anything by a dynamic key.
2. Using a Mapped Type or Record
Record<Keys, Value>
TypeScript provides a utility type called Record
:
const myObj: Record<string, number> = {}; myObj["age"] = 30; // ok myObj["width"] = 100; // ok // myObj["title"] = "some string"; // Error: not a number
- This is effectively a shorthand for
{ [key: string]: number }
.
Custom Mapped Types
If you have a finite set of known keys but want them dynamic in some sense, you can use a mapped type. However, usually that’s for known key unions rather than arbitrary keys. If you truly have arbitrary keys, Record<string, T>
or an index signature is simpler.
3. Type Assertions (Casting) / as any
If you don’t want to define an index signature or record, you can assert the object as any
(or a relevant type) at the point of assignment:
const myObj = {} as any; myObj.dynamicKey = "Hello"; myObj.someOtherKey = 123;
Caution: This bypasses TypeScript’s type safety. The compiler won’t check whether keys/values are valid. It’s a quick fix for “I know what I’m doing here,” but it can hide errors.
4. Example with a Function
function addDynamicProperty(obj: { [key: string]: any }, key: string, value: any): void { obj[key] = value; } const myObj: { [key: string]: any } = {}; addDynamicProperty(myObj, "name", "Alice"); addDynamicProperty(myObj, "age", 30); console.log(myObj); // { name: 'Alice', age: 30 }
- The function’s parameter
obj
has an index signature, so TypeScript allows anystring
key.
Choosing an Approach
- Index Signature: The typical approach when you have an object with truly dynamic keys. Provide the type for the values (
any
,string
, a custom interface, etc.). Record<Keys, Value>
: A good built-in type if all keys are strings (or a union of string literals) and you know the value type.- Casting to
any
: A quick fix, but you lose type-safety. - Mapped Types: More advanced scenario if you have a known set of keys but want dynamic transformation.
For everyday “store dynamic props in this object,” an index signature or Record<string, X>
is usually the cleanest solution.
Final Thoughts
TypeScript’s type system is designed to avoid unstructured “add whatever property you want” usage, because it can lead to confusion in larger codebases. But sometimes dynamic objects are necessary. In those cases, you’ll want to be explicit about how you’re storing these properties—index signatures or Record
are the most common ways to keep strong typing while still allowing dynamic property assignment.
Bonus: Strengthen Your JavaScript & TypeScript Core Knowledge
For a deeper dive into JavaScript fundamentals, which TypeScript builds upon, we recommend Grokking JavaScript Fundamentals. It covers:
- Closures & prototypes
- Async patterns
- Practical, real-world examples
Having a solid JS base helps you wield TypeScript effectively—especially when dealing with dynamic or advanced typing scenarios.