Borislav Hadzhiev
Mon Feb 28 2022·3 min read
Photo by Joanna Nix-Walkup
The "Property does not exist on type String" error occurs when we try to
access a property that does not exist on the string
type. To solve the error,
use an object instead of a string, or make sure you're accessing a valid
built-in method on the string.
Here is an example of how the error occurs.
const name = 'James'; // ⛔️ Error: Property 'id' does not // exist on type '"James"'.ts(2339) console.log(name.id);
We tried to access an id
property on a string. We got the error because the
id
property does not exist on strings.
If you didn't intend to access the property on a value of type string
, use
console.log
to log the value on which you are accessing the property.
To solve the error, use an object instead of a string and type the object's properties.
interface Person { name: string; id: number; } const p1: Person = { name: 'Tom', id: 1, }; console.log(p1.name); // 👉️ "Tom" console.log(p1.id); // 👉️ 1
We created an interface that contains the name
and id
properties. The p1
variable has a type of Person
, so we can safely access the name
and id
properties on the object.
If you need to initialize the object as empty, or with some key-value pairs missing initially, set the specific properties to optional by using a question mark.
interface Person { name?: string; id?: number; } const p1: Person = {}; p1.name = 'Tom'; p1.id = 1; console.log(p1.name); // 👉️ "Tom" console.log(p1.id); // 👉️ 1
We set the name
and id
properties to optional in the object, so we are able
to initialize the object as empty.
You can set the necessary properties at a later point in time.
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 Person = { [key: string]: any; name: string; }; const p1: Person = { name: 'Tom', }; p1.id = 1; p1.salary = 100; console.log(p1.name); // 👉️ "Tom" console.log(p1.test); // 👉️ undefined
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 basically 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 Person
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 Person = { [key: string]: string | number; name: string; id: number; }; const p1: Person = { name: 'Tom', id: 1, }; p1.job = 'accountant'; p1.salary = 100;
The index signature in the example above 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.
We had to use a union type, because both the 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 add another string key to the
interface that has a value of type number
.
type Person = { [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 above 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 number
.
To solve the "Property does not exist on type string" error, we have to make sure to only access built-in properties and methods on the string or use an object instead of a string.