Understanding this concept in TypeScript
can be a bit tricky and counterintuitive, but I'll do my best to explain it.
Let's begin with the following example:
named = course;
This code compiles without any issues because the interface Course
specifies a required property of name
, which is a string. The fact that both the interface and the object have an additional property called lessonCount
is not relevant as long as all the properties specified in the interface are present in the assigned type. Therefore, the type of named
remains as Named
, and attempting to access named.lessonCount
after assigning course
will result in an error. This behavior is known as Lenient type checking.
However, if you try to assign an object literal like this:
named = {name: 'sfdsf', lessonCount: 25};
The compiler will raise an error because the object literal includes a lessonCount
property that is not part of the Named
interface.
According to the TypeScript documentation:
Object literals undergo excess property checking when being assigned to other variables or passed as arguments. If an object literal contains properties not found in the "target type," an error will occur.
To resolve this issue, you can use a type assertion like so:
named = {name: 'sfdsf', lessonCount: 25} as Course;
You can learn more about this behavior in detail here.
Even though our object has additional properties, the compiler only checks for the presence of required properties matching the specified types.