Type Script Interface: As Object Or Array Type
Interface in TypeScript can be used to define a type and also to implement it in the class. The most scenarios can be summarized as following:
- as object type definition
- as array type definition
- as function type definition
- interface extends interface
- class implements interface
In this section, we mainly focus on the object and array type definition using interface. As function type definition will be introduced in Function: Types section.
Interface likes contract which defines the structure of the object, array, function and also class. However, we need to note that the TypeScript compiler does not convert interface to JavaScript. It uses interface for type checking.
Interface as object type
Normal case
TypeScript uses an interface to ensure the proper structure of an object. The following interface Person
defines a type of a variable:
interface Person {
name: string;
age: number;
}
In the above example, an interface Person
includes two properties name
and age
. Let's define some variables using this interface type:
let p1: Person = { name: 'kimi', age: 20 }; // OK
let p2: Person = { name: 'kimi', a: 20 }; // Error: 'a' does not exist in type 'Person'.
let p3: Person = { name: 'kimi', age: '100' }; // Error: Type 'string' is not assignable to type 'number'.
Indexable types
Indexable types have an index signature that describes the types we can use to index into the object, along with the corresponding return types when indexing. Let’s take an example:
interface Person {
name: string;
age: number;
[index: string]: any;
}
let p1: Person = { name: 'kimi', age: 20, gender: 'male' }; // OK
let p2: Person = { name: 'kimi', age: 20, id: 888 }; // OK
There are two types of supported index signatures: string
and number
. It is possible to support both types of indexers.
Recommend to use string indexer in object and numeric indexer in array.
Please pay more attention to return type, see following examplea:
interface Person {
name: string; // Error: Property 'name' of type 'string' is not assignable to string index type 'number'.
age: number; // OK
[index: string]: number;
}
interface Person {
name: string; // OK
age: number; // Error: Property 'age' of type 'number' is not assignable to string index type 'string'.
[index: string]: string;
}
You can imagine the [index: string]: string
as the types' "BOSS" in interface, if others match the "BOSS" pattern, the returned type must be compatible with "BOSS" otherwise will cause an error.
In addition, properties of different types are acceptable if the index signature is a union of the property types:
interface Person {
name: string; // OK
age: number; // OK
[index: string]: string | number;
}
Optional properties
Sometimes, we may declare an interface with excess properties but may not expect all objects to define all the given interface properties. We can have optional properties, marked with a ?
:
interface Person {
name: string;
age: number;
gender?: string;
}
In such cases, objects of the interface may or may not define these properties:
let p1: Person = { name: 'kimi', age: 20 }; // OK
let p2: Person = { name: 'kimi', age: 20, gender: 'male' }; // OK
Readonly properties
TypeScript provides a way to mark a property as read only. This means that once a property is assigned a value, it cannot be changed!
interface Person {
name: string;
readonly age: number;
}
let p1: Person = { name: 'kimi', age: 20 };
p1.age = 18; // Error: Cannot assign to 'age' because it is a read-only property.