TypeScript checks that the values of variables are the correct type and the same principle is applied to classes, objects, or contracts between your code. This is commonly known as "duck typing" or "structural sub-typing". Interfaces exist to fill this space and define these contracts or types.
Let's try to understand an interface with this example:
function greetingStudent(student: {name: string}){
console.log(`Hello ${student.name}`);
}
const newStudent = {name: 'Heitor'};
greetingStudent(newStudent);
The function will know that the object has the property name on it and that it's valid to call it.
We can rewrite it with the interface type for better code management:
interface IStudent {
name: string;
course?: string;
readonly university: string;
}
function greetingStudent(student: IStudent){
console.log(`Hello ${student.name}`);
if(student.course){
console.log(`Welcome to the ${student.course}` semester`);
}
}
const newStudent: IStudent = { name: 'Heitor', university: 'UDF' };
greetingStudent(newStudent);
As you can see, we have a new property called course that has a ? declared on it. This symbolizes that this property can be nulled or undefined. It's called an optional property.
There is a property with a read-only attribute declared. If we try to change after it's declared on the variable creation, we will receive a compile error because it makes the property read-only.