- Published on
Day14: Learning TypeScript: Interfaces
- Authors

- Name
- irisjustdoit
- @irisjustdoit
Day14:Learning TypeScript: Interfaces
A comprehensive note on interfaces. Finally, we arrive at interfaces, which I consider quite important. Let's take a look. This is probably the most serious note I've taken. Haha. I have seen it since I started learning, and I went from not understanding to having a rough understanding, and then to a deeper understanding, so I have been revising my notes. If there are any mistakes, please feel free to let me know!
Interfaces (介面)
In TypeScript, we use interfaces to define the types of objects, describing the shape of the object, including what properties and methods it has.
In object-oriented programming languages, interfaces are an important concept. They are an abstraction of behavior, while the specific actions need to be implemented by classes. More on classes will be noted later.
Defining an Interface
✅ Define an interface Person, and then define a variable iris whose type is IPerson. This constrains the shape of iris to match the IPerson interface. Interfaces generally start with an uppercase letter like Person, and some languages suggest prefixing with I like IPerson to indicate it is an interface. When assigning, the shape of the variable must match the shape of the interface.
interface IPerson {
name: string;
age: number;
}
const iris: IPerson = {
name: 'Iris',
age: 18
};
❌ It is not allowed for a variable to have more or fewer properties than the interface.
const iris: IPerson = {
name: 'Iris'
};
//error: Property 'age' is missing in type '{ name: string; }' but required in type 'IPerson'.
const iris: IPerson = {
name: 'Iris',
age: 18,
gender: 'female'
};
//error: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'IPerson'.
//Object literal may only specify known properties, and 'gender' does not exist in type 'IPerson'.
Optional Properties ?
You can add a ? after a property that does not need to be fully matched, indicating that the property may not exist. In the example below, the absence of the age property will not throw an error.
interface IPerson {
name: string;
age?: number;
}
const iris: IPerson = {
name: 'Iris'
};
Still Cannot Add or Remove Undefined Properties
If you still want to add a gender property, it will still throw an error.
interface IPerson {
name: string;
age?: number;
}
const iris: IPerson = {
name: 'Iris',
gender: 'female' // error: Property 'gender' is missing in type 'IPerson'.
};
Readonly Properties readonly
You can define a readonly property using readonly. The constraint exists when the "object" is first assigned, not when the "readonly property" is first assigned.
interface IPerson {
readonly id: number; // Readonly constraint
name: string;
age?: number;
[propName: string]: any;
}
const iris: IPerson = {
id: 89757, // If not provided, it will throw an error: Property 'id' is missing in type 'IPerson'.
name: 'Iris',
gender: 'female'
};
iris.id = 9527; // error: Cannot assign to 'id' because it is a read-only property.
Using Interfaces in Functions
In the greetPerson function, the person parameter type is IPerson, allowing access to the properties of IPerson.
interface IPerson {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
const iris: IPerson = {
id: 89757,
name: 'Iris',
gender: 'female'
};
const greetPerson = (person: IPerson) => {
console.log(`hi, ${person.name}!`);
}
greetPerson(iris); // hi, Iris!
Extending Types
Interfaces can also be extended. For example, if we have a BasicAddress type, but a certain area in the project requires an additional unit field, we can use extends to add the unit field, which is quite convenient and concise.
interface BasicAddress {
name?: string;
street: string;
city: string;
country: string;
postalCode: string;
}
interface AddressWithUnit extends BasicAddress {
unit: string;
}
Interfaces can also extend multiple interfaces:
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
interface ColorfulCircle extends Colorful, Circle {
background: string;
}
const cc: ColorfulCircle = {
color: "red",
radius: 42,
background: "white"
};
Interfaces Can Be Redefined
In the following example, if the gender property is missing, it will throw an error because TypeScript has merged the IPerson interfaces.
interface IPerson {
name: string;
}
interface IPerson {
age?: number;
}
interface IPerson {
gender: string;
}
const iris: IPerson = {
name: 'Iris',
age: 18
};
//error: Property 'gender' is missing in type '{ name: string; age: number; }' but required in type 'IPerson'.
TypeScript will merge interfaces with the same name, which is equivalent to:
interface IPerson {
name: string;
age: number;
gender: string;
}
Interfaces Can Define Arrays and Functions
We know that interfaces can define objects, but they can also define subtypes of objects, including arrays and functions.
Array:
interface INumberArray {
[index: number]: number;
}
const list: INumberArray = [1, 1, 2, 3, 5];
Function:
interface IPersonFunc {
(name: string, age: number): void;
}
Interfaces Can Have Function Overloads
Interfaces can also define function overloads. Function overloads refer to extending the forms in which a function can be executed.
interface IPoint {
getDist(): number;
getDist(x?: number): number;
}
const point: IPoint = {
getDist(x?: number) {
if (x && typeof x == "number") {
return x;
} else {
return 0;
}
}
}
console.log(point.getDist(20)); // 20
console.log(point.getDist()); // 0
Yay! I feel like I understand interfaces better now. Great! In the next article, I will introduce Type Aliases, which are quite similar to interfaces.
References
https://willh.gitbook.io/typescript-tutorial/basics/type-of-object-interfaces https://basarat.gitbook.io/typescript/type-system/interfaces
