Blog-Archiv

Donnerstag, 17. Mai 2018

No Private Names in TypeScript Classes

So we have been seduced to believe that TypeScript is very similar to Java. The longer I try it out the more I find out that it is not.

TS gives us access modifiers similar to Java:

  • public (visible for all, the default, a property or method without an access modifier is automatically public)
  • protected (visible for the own class and for sub-classes, other than in Java it is not visible for classes in same directory)
  • private (visible just for the own class)
  • readonly (instead of const inside classes, resembles Java final)

The Java default access modifier (package-visibility, active when no modifier was defined) is not present in TS, because no package-concept exists.

Private Is Not Quite Private

Access modifiers promise something that never has been standardized. Thus the Scala programmer may expect something different than the C++ or Java programmer. Let's try out private in TypeScript.

I know, it is ridiculous to derive FlagShip from Flag, but look how I defined private properties in these classes:

Flag.ts
export class Flag
{
    private readonly defaultValue: boolean = false;
}
FlagShip.ts
import { Flag } from "./Flag.js";

export class FlagShip extends Flag
{
    private readonly defaultValue: boolean = true;
}

Try to compile this by

tsc -t ES6 *.ts

You will see following error:

error TS2415: Class 'FlagShip' incorrectly extends base class 'Flag'.
  Types have separate declarations of a private property 'defaultValue'.

So not each of the two classes can have its own private defaultValue property? What kind of privacy is this?

However, we must fix it by thinking about some useful name that can replace defaultValue in class FlagShip. I changed it to be shipDefaultValue.

But, to challenge fate, I added two private methods of same name now.

Flag.ts
export class Flag
{
    private readonly defaultValue: boolean = false;
    
    private getDefaultValue(): boolean {
        return this.defaultValue;
    }
}
FlagShip.ts
import { Flag } from "./Flag.js";

export class FlagShip extends Flag
{
    private readonly shipDefaultValue: boolean = true;
    
    private getDefaultValue(): boolean {
        return this.shipDefaultValue;
    }
}

Another compile error shows up:

error TS2415: Class 'FlagShip' incorrectly extends base class 'Flag'.
  Types have separate declarations of a private property 'getDefaultValue'.

So, getDefaultValue is a "property"? Isn't this called "method", or at least "function"?

What we learn is that private in TS means invisible to the outer world, but not to the compiler.

Conclusion

If something is quacking, it is not necessarily a duck. I will explore TS access modifiers further in future Blogs.




Keine Kommentare: