Borislav Hadzhiev
Tue Mar 01 2022·3 min read
Photo by Lê Tân
Use a type assertion to initialize a typed, empty object using an interface in
TypeScript, e.g. const emp1 = {} as MyInterface
. You can access or set any
properties on the object, as long as they exist on the interface and are
compatible with the corresponding types.
interface Employee { id: number; name: string; salary: number; } const emp1 = {} as Employee; emp1.id = 1; emp1.name = 'Alice'; emp1.salary = 100;
We used a type assertion to declare an empty object for a typed variable.
This is often the case when fetching data from a remote source like a database. In this situation, you can use a type assertion to cast the variable to a specific type.
If you try to add a property to the object that doesn't conform to the properties in the interface, you'd get an error.
interface Employee { id: number; name: string; salary: number; } const emp1 = {} as Employee; // ⛔️ Error: Property 'example' does // not exist on type 'Employee'.ts(2339) emp1.example = 'hello';
The emp1
variable has a type of Employee
, so trying to set a property that
is not compatible with the type gets us an error.
However, one thing to be aware of is - you're not required to set all of the required properties of the specific interface once you've used a type assertion.
interface Employee { id: number; name: string; salary: number; } const emp1 = {} as Employee; emp1.id = 1; // ✅ OK
We've told TypeScript that the emp1
variable stores an Employee
type, so it
already assumes that the emp1
variable has all of the properties an Employee
type has.
Alternatively, you can use the Partial
utility type and set all of the
properties in the interface to optional.
interface Employee { id: number; name: string; } const emp1: Partial<Employee> = {}; emp1.id = 1; emp1.name = 'Alice';
The Partial utility type enables us to set all of the properties of the type to optional.
This way we can declare the typed variable to an empty object without getting an error.
Animal
type are optional.If you don't know all of the names of the type's properties ahead of time, use an index signature.
interface Employee { id: number; name: string; [key: string]: any; } const emp1 = {} as Employee; emp1.id = 1; emp1.name = 'Alice'; emp1.years = [2022, 2023]; emp1.salary = 100;
The {[key: string]: any}
syntax is an
index signature
in TypeScript and is used when we don't know all the names of a type's
properties and the shape of the values ahead of time.
string
, it will return a value of any
type.You might also see the index signature {[key: string]: string}
in examples. It
represents a key-value structure that when indexed with a string
returns a
value of type string
.
years
and salary
properties to the object, even though they aren't present in the interface.If you don't know all of the property names of the type, but know the shape of the values, create a more specific index signature for better type safety.
interface Employee { id: number; name: string; [key: string]: string | number | number[]; } const emp1: Partial<Employee> = {}; emp1.id = 1; emp1.name = 'Alice'; emp1.years = [2022, 2023]; emp1.salary = 100; emp1.department = 'accounting';
The index signature in the example means that when the object is indexed with a
string key, it will return a value that has a type of string
, number
or
number[]
.