Consider the following example of TypeScript code:
const organization = {} organization.name = "Logrocket"
This seemingly harmless piece of code throws a TypeScript error on dynamically assigning name
to the organization
object.

See this example in the TypeScript Playground.
The source of confusion, which is perhaps rightly justified if you’re a TypeScript beginner, is: how could something that seems so simple be such a problem in TypeScript?
The TL;DR of it all is that, if you cannot define the variable type at declaration time, you can use the Record
utility type or an object index signature to solve this. But in this post, we’ll go through the problem itself and work toward a solution that should work in most cases.
Jump ahead:
Understanding the problem with dynamically assigning properties to objects
Generally speaking, TypeScript determines the type of a variable when it is declared, and this determined type doesn’t change, i.e., it stays the same all through your application.
There are exceptions to this rule, such as when considering type narrowing or working with the any
type, but this is a general rule to remember otherwise.
In the earlier example, the organization
object is declared as follows:
const organization = {}
There is no explicit type assigned to the organization
variable, so TypeScript infers a type of organization
based on the declaration to be {}
, i.e., the literal empty object.
For example, if you add a type alias, you can explore the type of organization
:
type Org = typeof organization

See this in the TypeScript Playground.
When you then try to reference the name
prop on this empty object literal:
organization.name = ...
TypeScript yells.
Property ‘name’ does not exist on type ‘
{}
‘
When you understand the issue, the error does seem appropriate.
Let’s fix this.
Resolving the problem
There are numerous ways you can resolve the TypeScript error here. Let’s consider these:
Solution 1: Explicitly type the object at declaration time
This is the easiest solution to reason through. At the time you declare the object, go ahead and type it. Furthermore, assign it all the relevant values.
type Org = { name: string } const organization: Org = { name: "Logrocket" }
See this in the TypeScript Playground.
This eliminates any surprises. You’re clearly stating what this object type is and rightly declaring all relevant properties when you create the object.
However, this is not always feasible if the object properties must be added dynamically, which is why we’re all here.
Solution 2: Use an object index signature
Occasionally, the properties of the object truly need to be added at a time after they’ve been declared. In this case, you can use the object index signature, as follows:
type Org = {[key: string] : string} const organization: Org = {} organization.name = "Logrocket"
See this in the TypeScript Playground.
At the time the organization
variable is declared, you can go ahead and explicitly type it to the following {[key: string] : string}
.
To explain the syntax further, you might be used to object types having fixed property types:
type obj = { name: string }
However, you can also substitute name
for a “variable type”.
For example, if you want to define any string property on obj
:
type obj = { [key: string]: string }
Note that the syntax is similar to how you’d use a variable object property in standard JavaScript:
const variable = "name" const obj = { [variable]: "Freecodecamp" }
The TypeScript equivalent is called an object index signature. Moreover, note that you could type key
with other primitives:
// number type Org = {[key: number] : string} // string type Org = {[key: string] : string} //boolean type Org = {[key: boolean] : string}
Solution 3: Use the Record
utility type
The Record
utility type allows you to constrict 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 string
and Type
, string
as well. The solution here is quite concise as shown below:
type Org = Record<string, string> const organization: Org = {} organization.name = "Logrocket"
Instead of using a type alias, you can also inline the type:
const organization: Record<string, string> = {}

Record
utility typeSee this in the TypeScript Playground.
Solution 4: Use the Map
data type
Now, a Map
object is a fundamentally different data structure from an object
, but for completeness, you could eliminate this problem if you were using a Map
.
Consider the starting example rewritten to use a Map
object:
// before const organization = {} organization.name = "Logrocket" // after const organization = new Map() organization.set("name","Logrocket")
With Map
objects, you’ll have no errors when dynamically assigning properties to the object:
See this in the TypeScript playground.
This seems like a great solution at first, but the caveat is your Map
object is weakly typed. You can access a nonexisting property and get no warnings at all:
const organization = new Map() organization.set("name","Logrocket") // Property nothingness does not exist. No TS warnings const s = organization.get("nothingness") console.log(s)
See the TypeScript playground.
This is unlike the standard object.
By default, the initialized Map
has the key and value types as any
— i.e., new () => Map
. Consequently, the return type of the s
variable will be any
:
When using a Map
, at the very least, I strongly suggest passing some type information upon creation. For example:
const organization = new Map<string, string>() organization.set("name","Logrocket") const s = organization.get("nothingness") console.log(s)
s
will still be undefined, but you won’t be surprised by its code usage. You’ll now receive the appropriate type for it:
If you truly don’t know what the keys
of the Map
will be, you can go ahead and represent this at the type level:
const organization = new Map<unknown, string>()
And if you’re not sure what the keys
or values
are, be safe by representing this at the type level:
const organization = new Map<unknown, unknown>()
Solution 5: Consider an optional object
property
This solution won’t always be possible, but if you know know the name of the property to be dynamically assigned, you can go ahead to optionally provide this when initializing the object as shown below:
const organization : {name?: string} = {} organization.name = "Logrocket"
See the TypeScript playground.
If you don’t like the idea of using optional properties, you can be more explicit with your typing as shown below:
const organization : {name: string | null} = { name: null } organization.name = "Logrocket"
See the TypeScript playground.
Conclusion
Apart from primitives, the most common types you’ll have to deal with are likely object types.
In cases where you need to build an object dynamically, take advantage of the Record
utility type or use the object index signature to define the allowed properties on the object.
If you’d like to read more on this subject, feel free to 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 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.
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.