Last updated: Feb 27, 2024
Reading time·7 min

Object type when typing objectsThe "Property does not exist on type '{}'" error occurs when we try to access or set a property that is not contained in the object's type.
To solve the error, type the object properties explicitly or use a type with variable key names.
Here is an example of how the error occurs:
const obj = {}; // ⛔️ Error: Property 'name' does not exist on type '{}'.ts(2339) obj.name = 'Bobby Hadz';

You might also get the error if you use the Object type.
const obj: Object = {}; // ⛔️ Property 'name' does not exist on type 'Object'. obj.name = 'Bobby Hadz';
We didn't explicitly type the obj variable and initialized it to an empty
object, so we aren't able to assign or access properties that don't exist on the
object's type.
To solve the error, type the object explicitly and specify all of the properties you intend to access.
// ✅ When you know property names ahead of time type Employee = { id?: number; name?: string; }; const obj: Employee = {}; obj.id = 1; obj.name = 'Bobby Hadz';

If you don't know all of the property names ahead of time, use an index signature.
// ✅ When you don't know ALL property names ahead of time type Employee = { [key: string]: any; // 👈️ variable key name: string; }; const obj: Employee = { name: 'Bobby Hadz', }; obj.salary = 100;

The first example shows how to type an object when you know its property names and the type of its values ahead of time.
We need to declare the object as empty, so we marked the properties as optional by using a question mark.
// ✅ When you know property names ahead of time type Employee = { id?: number; name?: string; }; const obj: Employee = {}; obj.id = 1; obj.name = 'Bobby Hadz';

id and name properties can be assigned later on.The properties exist on the object's type, so we won't get the "Property does not exist on type 'Object'" error when accessing them.
You can also
make all of an object's properties optional
by using the Partial type.
In some cases, you won't know the names of all of the object's keys or the shape of the values ahead of time.
type Employee = { [key: string]: any; // 👈️ variable key name: string; }; const obj: Employee = { name: 'Bobby Hadz', }; obj.salary = 100;

The {[key: string]: any} syntax is called an index signature and is used when you don't know the names of the object's keys or the shape of the values ahead of time.
The syntax means that when the object is indexed with a string key, it will
return a value of any type.
We set the name property to string in the Employee type, so the type
checker would throw an error if the property is not provided or is set to a
value of a different type.
If you don't know the names of all of the object's keys but know the shape of the values, you can use a more specific index signature for better type safety.
type Employee = { [key: string]: string | number; name: string; id: number; }; const obj: Employee = { id: 1, name: 'Bobby Hadz', }; obj.department = 'accounting'; obj.salary = 100;

The index signature means that when the object is indexed with a string key, it
will return a value that has a string or number type.
The string | number syntax is called a
union type in TypeScript.
name and id properties are strings and they return different types.In other words, you can't specify that when the object is indexed with a string
key, it returns a value of type string and then add another string key to the
interface that has a value of
type number.
type Employee = { [key: string]: string; name: string; // ⛔️ Error: Property 'id' of type 'number' is // not assignable to 'string' index type 'string'.ts(2411) id: number; };
The example shows that the type checker throws an error if we specify that when
indexed with a string key, the object returns a value of type string and try
to add another string key that has a value of type number.
any type if you want to turn off type-checkingIf you just want to turn off type checking and be able to add any property to
the object, set its type to any.
const obj: any = {}; obj.name = 'Bobby Hadz'; obj.age = 30; console.log(obj); // 👉️ { name: 'Bobby Hadz', age: 30 }

The any type effectively
turns off type checking and enables us
to add any property to the object.
However, when we use this approach we don't take advantage of the benefits that TypeScript provides.
Object type when typing objectsThe following code sample raises the same error when we try to access a property that doesn't exist on the object's type.
const obj: Object = { name: 'Bobby Hadz', age: 30, }; // ⛔️ Error: Property 'country' does not exist on type 'Object'.ts(2339) obj.country = 'Chile';
We typed the obj variable as Object and tried to access the country
property on the object.
country property does not exist on the Object type, so the type checker throws an error.This is only 1 of the issues in the code sample.
The Object type should never be used to type a value in TypeScript.
The Object type means "any non-nullish value". In other words, it means any
value that is not null or undefined.
The "property does not exist on type union" error occurs when we try to access a property that is not present on every object in the union type.
To solve the error, use a type guard to ensure the property exists on the object before accessing it.
Here is an example of how the error occurs.
type Person = { age: number; }; type Employee = { salary: number; }; function getProperty(obj: Person | Employee): number { // ⛔️ Error: Property 'age' does not exist on type 'Person | Employee'. if (obj.age) { return obj.age; } return obj.salary; }

The age property doesn't exist on all of the types in the
union,
so we aren't able to access it directly.
Instead, we have to use a type guard to check if the property exists in the object before accessing it.
type Person = { age: number; }; type Employee = { salary: number; }; function getProperty(obj: Person | Employee): number { if ('age' in obj) { return obj.age; } return obj.salary; }
We used the in operator, which is a type guard in TypeScript.
The in operator returns true if the specified property is in the object or
its prototype chain.
const obj = { a: 'hello', }; console.log('a' in obj); // 👉️ true console.log('b' in obj); // 👉️ false
This way, TypeScript can infer the type of the object in the if block and
after the if block.
type Person = { age: number; }; type Employee = { salary: number; }; function getProperty(obj: Person | Employee): number { if ('age' in obj) { // 👇️ now `obj` is type `Person` return obj.age; } // 👇️ now `obj` is type `Employee` return obj.salary; }
age property is contained in the passed-in object, we can safely use the age property and TypeScript is able to infer the type of obj to be Person.If the if block doesn't run, then the age property isn't in the passed-in
object and TypeScript infers the type of obj to be Employee.
If you need to check if a string is in a union type, click on the following article.
The error "Property 'status' does not exist on type 'Error'" occurs because
the status property is not available on the Error interface.
To solve the error, add the specific property to the Error interface or
create a custom class that extends from Error.

Here is an example of how the error occurs.
const err = new Error('Something went wrong'); // ⛔️ Property 'status' does not exist on type 'Error'.ts(2339) err.status = 500; // ⛔️ Property 'code' does not exist on type 'Error'.ts(2339) console.log(err.code);
The reason we got the errors in the example above is that the status and
code properties don't exist on the Error interface.
By default, the Error interface has the following properties:
interface Error { name: string; message: string; stack?: string; }
To get around this, we can extend the Error class.
export class CustomError extends Error { status: number = 200; code: number = 200; constructor(message: string) { super(message); // 👇️ because we are extending a built-in class Object.setPrototypeOf(this, CustomError.prototype); } } const err = new CustomError('Something went wrong'); err.status = 500; console.log(err.status); err.code = 500; console.log(err.code);
The CustomError class extends from the built-in Error class and adds the
status and code properties.
If you want to read more on how to extend from the Error class in TypeScript,
check out this article.
You can learn more about the related topics by checking out the following tutorials: