TypeScript’s Evolutionary Cruft: Class Access Modifiers

TypeScript’s Evolutionary Cruft: Class Access ModifiersBraden SnellBlockedUnblockFollowFollowingJan 5IntroductionFirst, let’s make sure one thing is clear: TypeScript is a fantastic tool.

It provides a developer experience that is second to none.

Its core team is responsive to the community and their pace of innovation is remarkable.

TypeScript is quickly taking over the world of complex JavaScript applications and that is a very good thing.

It’s not all sunshine and rainbows though: in order to achieve the level of popularity it has today, the TypeScript team needed to make decisions that were “right at the time”.

For instance, when TypeScript was released bundlers like webpack didn’t yet exist.

To bridge the gap, TypeScript shipped with a feature called internal modules (known today as namespaces) for client-side applications.

Internal modules are no longer necessary, but, the TypeScript team’s strong commitment to ensuring new versions of the language don’t break existing code, means internal modules are still part of the language.

Fortunately, linters provide a consistent way to avoid such vestigial features.

Class access modifiers are one of these features that can (and should) be linted away.

This post is part of a series on TypeScript’s “evolutionary cruft” and how the linting rules in ts-cruftless can help you avoid some of TypeScript’s more problematic language features.

Find links to the other posts here.

Class Access ModifiersHere’s an example of what class access modifiers look like:class Example { accessibleEverywhere; public alsoAccessibleEverywhere; private accessibleOnlyInThisClass; // A deriving class would be any class which extends // "Example" either directly (e.

g.

class Foo extends Example {}) // or indirectly (e.

g.

class Bar extends Foo {}) protected accessibleInThisClassAndInDerivingClasses;}The keywords public private and protected can appear before class properties and methods.

If no access modifier is present, class properties and methods are public by default.

TypeScript’s documentation explains the concept more thoroughly if you’d like more details.

There was no concept of classes — let alone access modifiers — in JavaScript when TypeScript was first introduced.

Over the years, TC39 (the governing body of the ECMAScript standard on which JavaScript is based) has introduced classes and is coming very close to finalizing a set of proposals which include some of the functionality of TypeScript’s access modifiers feature.

Fortunately, classes in TypeScript are virtually identical to classes in JavaScript.

Unfortunately, class access modifiers will not share the same level of similarity.

Here’s a quick peek at what JavaScript’s future syntax for access modifiers may look like:class Example { accessibleEverywhere; #accessibleOnlyInThisClass;}Check out the proposals linked to above if you’re interested in more details of how this will work.

You’ll notice there is only the concept of private and public and no concept of protected.

The syntax also is quite different with # replacing private and no way to explicitly declare a property or method as public.

TypeScript’s guiding directive, to track the ECMAScript standard as close as possible and innovate in the type system, doesn’t align well with the proposed state of the language in this area.

It might be speculated that TypeScript’s original target audience of Java and C# developers motivated the initial inclusion of access modifiers in the language.

While object-orientation may have been where TypeScript started, the language and its core team have since come to embrace many of the functional patterns popular in the JavaScript world today.

Interestingly, several years ago, the TypeScript compiler underwent a complete rewrite where all classes were dropped and a very functional code base was adopted.

Whatever the reasons around the initial language design of class access modifiers, it can be safely said that if TypeScript were being released today its story around the subject would have been very different.

The new ECMAScript proposals around private class properties/methods make TypeScript’s class access modifiers feature partially redundant.

Additionally, this feature is definitely out of touch with the current prevailing style of JavaScript programming which eschews heavily object-oriented architectures.

But, breaking existing code is something the TypeScript team will rarely do, so today’s version of class access modifiers is likely to be in the language for years to come.

Keep in mind, however, that this feature may be an example of a “right at the time” decision that helped lead TypeScript to where it is today.

So, even if you don’t like public private and protected you should be grateful for them :)Enter ts-cruftlessHere’s the good news: even if the TypeScript team won’t break people’s code and remove this feature, you can!.How?.Use TSLint and add the ts-cruftless package to your project.

ts-cruftless is a small set of linter rules created to prevent TypeScript’s evolutionary cruft from rearing its head in your codebase.

These rules are designed to help keep your TypeScript code as close to idiomatic JavaScript as possible while still allowing you to embrace the amazing tooling TypeScript provides.

Agree?.Disagree?.Talk about it in the comments or head over to the ts-cruftless repository and join/start a discussion on the issue tracker.

.. More details

Leave a Reply