Borislav Hadzhiev
Mon Feb 28 2022·3 min read
Photo by Lê Tân
The "Object literal may only specify known properties" error occurs when a property in an object literal does not exist in the object's type. To solve the error, make sure to type all of the object's properties and fix spelling errors in property names if you have any.
Here is an example of how the error occurs.
type Employee = { id: number; }; // ⛔️ Object literal may only specify known // properties, and 'name' does not exist in type 'Employee'. const emp: Employee = { id: 1, name: 'Alice' };
The Employee
type only has an id
property, so when we try to assign a name
property to an object of type Employee
, the error is thrown.
To solve this, make sure to type of all of properties the object literal will have (if yo know the property names ahead of time).
type Employee = { id: number; name: string; }; const emp: Employee = { id: 1, name: 'Alice' };
We added the name
property to the Employee
type, so the type checker does
not throw the error anymore.
Sometimes you don't know the names of all of the properties in the object ahead of time. In this case, use an index signature.
type Employee = { id: number; [key: string]: any; }; const emp: Employee = { id: 1, name: 'Alice', department: 'accounting' };
The {[key: string]: any}
syntax is called an index signature and is used when
we don't know all of the object's property names and the shape of the values
ahead of time.
string
key, it will return a value of any
type (very broad).Notice that we are still able to specify the id
property, setting it to
number
, because we know all objects of type Employee
will have it.
You should always explicitly specify the properties you know about when using this approach, because it gets us better type checking.
If you don't know all of the object's property names, but you know the shape of the values, you can use a stricter index signature for better type safety.
type Employee = { id: number; [key: string]: string | number; }; const emp: Employee = { id: 1, name: 'Alice', department: 'accounting', salary: 100, };
The {[key: string]: string | number}
syntax means that when the object is
indexed with a string key, it will return a value that is of type string
or
number
.
The string | number
syntax is called a
union type
in TypeScript.
Now we are able to add any properties to the object that have a value of type
string
or number
, which is much better for type safety than specifying a
value of type any
.
Note that when using this approach, you aren't able to add string keys that have
a value of type other than string | number
.
type Employee = { id: number; [key: string]: string | number; // ⛔️ Error: Property 'years' of type 'number[]' // is not assignable to 'string' index type 'string | number'. years: number[]; };
With our index signature of [key: string]: string | number
, we told TypeScript
that when a string key is accessed, it will return a value that is a string
or
a number
, so we can't add another string key that has a type of number[]
.
To solve this, you have to add number[]
to the union type.
type Employee = { id: number; [key: string]: string | number | number[]; years: number[]; }; const emp: Employee = { id: 1, name: 'Alice', department: 'accounting', salary: 100, years: [2022, 2023], };
If you are unsure what properties the object will contain, but generally know that it will be one of X types, use a union type.
class Bird { fly() { console.log('bird flies'); } } class Fish { swim() { console.log('fish swims'); } } let obj: Bird | Fish; // 👇️ (your condition here) if (Math.random() > 0.5) { obj = new Bird(); } else { obj = new Fish(); } console.log(obj); // 👉️ Bird {}
The obj
variable stores an object of type Bird
or Fish
.
If a condition is met, we assign a Bird
instance to the object, else we assign
a Fish
instance to the object.
We are able to assign either value to the object, because we used a union type.