Typescript: Class implements class !

Created on 27 Jan 2020  Β·  6Comments  Β·  Source: microsoft/TypeScript

TypeScript Version: 3.7.5


Search Terms: typescript class implements class

Expected behavior: Compilation error : A class cannot implements another class. A class can extend a class, extends an abstract class or implements an interface.

Actual behavior: No error !


Related Issues:

Code

class MaClasse {
  maFunc(): boolean {
    return true;
  }
}
​
class AutreClasse implements MaClasse {
  maFunc() {
    return true;
  }
}

Output

"use strict";
class MaClasse {
    maFunc() {
        return true;
    }
}
class AutreClasse {
    maFunc() {
        return true;
    }
}

Compiler Options

{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "useDefineForClassFields": false,
    "alwaysStrict": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "downlevelIteration": false,
    "noEmitHelpers": false,
    "noLib": false,
    "noStrictGenericChecks": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "esModuleInterop": true,
    "preserveConstEnums": false,
    "removeComments": false,
    "skipLibCheck": false,
    "checkJs": false,
    "allowJs": false,
    "declaration": true,
    "experimentalDecorators": false,
    "emitDecoratorMetadata": false,
    "target": "ES2017",
    "module": "ESNext"
  }
}

Playground Link: Provided

Working as Intended

Most helpful comment

Relevant Stack Overflow question

I don't see an explicit piece of handbook documentation that says "yes, it is legal when a class implements another class". The closest is the section that says "yes, it is legal when an interface extends a class"... which implies that at the very least the following two-step process is legal:

class C { /* ... */ }
interface I extends C { /* ... */ }
class C2 extends I { /* ... * / }

And it isn't much of a jump to expect that you don't need the intervening interface.

It would be nice if there were more explicit official documentation about this stuff, but until then if something is surprising then a good first step is to ask in help forums about it before assuming it's a bug. Of course sometimes these things do turn out to be bugs, so it's good to look into things that are confusing or surprising.

If we interpret this as a feature request "prohibit implementing a class" then it will likely be declined as it would break a bunch of existing code with the only benefit being to promote a particular ideology about what constitutes correct object oriented programming. In TS as designed, a class named Foo has a type named Foo which can be used like an interface everywhere. If you change your viewpoint from "a class implementing another class" to "a class implementing another class's interface" then it might be less objectionable to you.

Good luck!

All 6 comments

@ilogico your feedback can be interesting. do not hesitate to share it in writing for better understanding

When you define a class, you define both a value (the constructor) and an interface (implemented by the objects constructed by the constructor).
These interfaces can be extended by other interfaces and implemented by other classes.
This is working as designed.

(I believe this is question/doubt you have about TypeScript, which should be posted in help forums and not an issue with the TypeScript language or compiler, hence the down vote.)

In fact I was surprised by this mechanism/design "class that implements a class". Conceptually, I have never seen/read this in the Object Oriented Approach. But if typescript is designed like that, why not ... this will make it exclusive... I prefer the original concepts of the object oriented approach.

The official Typescript documentation never talks clearly about this "class that implements a class" mechanism.

Edit/Update:
When the doc talks about abstraction/implementation it's always with the interfaces.

That's why I say to myself, it can be a permissiveness as we have it in Javascript, and not a concept. If it was a concept, we will find it very clear in the doc.

Relevant Stack Overflow question

I don't see an explicit piece of handbook documentation that says "yes, it is legal when a class implements another class". The closest is the section that says "yes, it is legal when an interface extends a class"... which implies that at the very least the following two-step process is legal:

class C { /* ... */ }
interface I extends C { /* ... */ }
class C2 extends I { /* ... * / }

And it isn't much of a jump to expect that you don't need the intervening interface.

It would be nice if there were more explicit official documentation about this stuff, but until then if something is surprising then a good first step is to ask in help forums about it before assuming it's a bug. Of course sometimes these things do turn out to be bugs, so it's good to look into things that are confusing or surprising.

If we interpret this as a feature request "prohibit implementing a class" then it will likely be declined as it would break a bunch of existing code with the only benefit being to promote a particular ideology about what constitutes correct object oriented programming. In TS as designed, a class named Foo has a type named Foo which can be used like an interface everywhere. If you change your viewpoint from "a class implementing another class" to "a class implementing another class's interface" then it might be less objectionable to you.

Good luck!

When the doc talks about abstraction/implementation it's always with interfaces.

That's why I say to myself, it can be a permissiveness as we have in Javascript, and not a concept of typescript. If it was a concept, we will find it very clear in the doc.

Would be happy to take a good PR to the docs, but the behavior described is intended.

Was this page helpful?
0 / 5 - 0 ratings