I am new to Typescript and ran into the following question when trying to implement a interface in a class:
interface TestInterface {
x: number
}
class Test implements TestInterface {
constructor() {
this.x = 0
}
}
// Class 'Test' incorrectly implements interface 'TestInterface'.
// Property 'x' is missing in type 'Test' but required in type 'TestInterface'.
But if I add x: number
to Test
before constructor
, it works. So I am guessing if you wanted to check the type of a property initialized in the constructor
, you have to specify that on the class itself. Then what is implement
and the interface
for? And if I want to use the interface to check the type of its instances, wouldn't it be repetitive since I have to write it in two places?
Code in a constructor is not something that Typescript can check to determine if your class correctly implements the interface. It would be impossible for Typescript to check all the assignments in your code to ensure the types are correct, so you need to declare the types statically. The point of interface
and implements
is not to reduce the amount of code you have to write, it's to declare the type of objects in your code, so that Typescript can statically check that your code is self-consistent with regard to types.
By saying the class implements the interface, you are effectively asking Typescript to keep you honest and check that the types are indeed consistent. If Typescript merely trusted that you'd do the right thing in your constructor, it would not be very effective! Note that constructors may contain conditional logic, loops and other code that mean it is not possible even in principle for Typescript to analyse the constructor code to determine if you are keeping the contract you commit to with implements
.
So I am guessing if you wanted to check the type of a property initialized in the constructor, you have to specify that on the class itself.
You are exactly right!
Then what is implement and the interface for?
An interface is intended to be a "contract". Here's a simple example:
interface Connectable {
connect: () => Promise<void>
}
const robustConnect = async (connection: Connectable) => {
try {
await connection.connect();
} catch (error) {
console.warn(`there was an error, let's try once more`);
await connection.connect();
}
}
In this example, we've typed the function robustConnect
so that it can receive just any object that has a connect
method. This is the most useful usage of an interface: giving a name to a type so that it is more legible.
In other OO languages, an interface would be the only way to declare a type like that, and you would have to extend the interface to use robustConnect
. Otherwise, the compilation step would fail. Since javascript isn't inherently an object-oriented language and is dynamically typed, that restriction isn't there. So the implements
keyword can feel useless. At best, you could use it to help yourself when writing classes: just use the implements
keyword and let the TypeScript compiler tell you what you are missing. But that's about it.
Hope this helps.
Low key You need to learn Object Oriented Programming. Your question is a core principle of oop.
When you find a new job, you sign a contract, the contract specifies your role, duties, behavior and more; so you need to follow the contract so if you implement an interface your class need to follow the structure of your interface.
If for instance you find that redundant instead of creating a class use pure objects
const obj:Obj ={
name: “eneto”
};
Plus also your statement “But if I add x: number to Test before constructor, it works. So I am guessing if you wanted to check the type of a property initialized in the constructor, you have to specify that on the class itself. Then what is implement and the interface for?” doesn’t have sense, because typescript checks your code at compilation fase, but once your code compiles it becomes JavaScript which doesn’t have static types