DEV Community

TypeScript -- why not?

Dmitry Amelchenko on January 19, 2021

I just recently watched https://www.udemy.com/course/typescript-for-javascript-developers , While watching it, I could not help but to keep think...
Collapse
 
rxliuli profile image
rxliuli

I moved to ts in late 2018 and started to get very frustrated -- because I was refactoring generic libraries using ts and it contained functionally relevant functionality. For a year or so afterwards, my opinion of ts had been that it was overly complex and hard to learn, and I even once bought the domain typescript.icu with the intention of criticizing it.
But now, two years later, I believe that the front-end cannot support large-scale project development without ts. In particular, IDE support for ts refactoring, navigation, and hinting is a far cry from js! The type complexity it brings is aimed more at the library than the average developer, and it's always better for the library developer to do more than for the user to do more.

--

Some previous tweets

Having used TypeScript for some time now, I have to state here again that the type system in TypeScript is more complex than you can imagine, and if you are not ready to use it in a production system, it is better not to use it. The lack of explanation of the type system (especially native types, such as PromiseLike, which no one has talked about) makes TypeScript's type system seem like it's just for fun a lot of the time. And for slightly more complex cases, the time spent thinking about how to design types will outweigh the time spent implementing the code, so please think twice about using it!

TypeScript's type system is far too flawed for JavaScript compatibility.

See what a user said:

  1. ts can't write a way to merge objects

Here's a js method for merging objects

   function extend(dest, ... . sources) {
     return Object.assign(dest, . . sources)
   }
Enter fullscreen mode Exit fullscreen mode

With such a simple approach, ts can't write an implementation that doesn't lose type information.

The following is the declaration of Object.assign in the typescript source code, and I'm sure you can see how silly it is.

   assign<T, U>(target: T, source: U): T & U;
   assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
   assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & & W;
   assign(target: object, . . sources: any[]): any;
Enter fullscreen mode Exit fullscreen mode

According to this implementation, more than 4 arguments will just throw away the type information. ts is recommended to use at least A-Z as generic quantities... 2.

  1. some obvious type inferences are not inferred

It is common practice to use the assert method for parameter checking, a simple assert method is

   function assert(condition, msg) {
     if (condition) throw new Error(msg)
   }
Enter fullscreen mode Exit fullscreen mode

Then look at a piece of code like this.

   function foo(p: number | string) {
     assert(typeof p === 'number', 'p is a number')
     p.length // here is an error, ts doesn't know that p must be a string by this point
   }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
dmitryame profile image
Dmitry Amelchenko

I don’t mean to start another religious war here, but… Based on my experience, the most messiest apps I’ve ever see were written in C++ and Java — both compiled languages. It’s not the compiled vs. interpreted — it’s all about quality of developers. Good developers tend to prefer interpreted languages and duck typing (rather than strong typing). Good developers tend to perfect the basic language skills and learn language idiomatic way of solving issue, rather than relying on static or dynamic analysis tools. Good (lazy) developers, spend time to write less code. Compiled type checking may help to some degree, but it’s wrongfully shifting focus on writing more code in different syntax (which one must learn and perfect), rather than worrying about higher level concepts like code duplication, declarative programming etc…

Collapse
 
curtisfenner profile image
Curtis Fenner

TypeScript doesn't attempt to "hide the JS ugliness" -- TypeScript has exactly the same runtime semantics as JavaScript. It's impossible to learn TypeScript without also learning JavaScript, and since valid JavaScript is truly a subset of TypeScript, if you have learned JavaScript you have also learned TypeScript.

The version history of JavaScript, idiosyncratic standard library, the way prototypes and inheritance works, automatic conversions, etc. are all components of TypeScript, because all JavaScript is also TypeScript.

The purpose of TypeScript is to manage complexity. Machine-checked types let you communicate faster:

  • You can suddenly communicate with the IDE, since the IDE now understands what properties and methods are available (e.g., auto-completion), and what arguments are legal and illegal (e.g., oops, this argument isn't nullable, or you typo'd an enum value in your configuration)
  • You can communicate with other developers faster than without types:
    • Comments can lie, types don't (as often) -- you don't have to double check things, because the compiler has double checked them for you
    • The type signature is dramatically shorter than the implementation, so you can just read that and use the module written by someone else, instead of the extensive code or docs
    • Many/most type-signatures are inferred, so they're "there" without the writer needing to actually embed them in the source code -- this is like getting documentation for your functions being written for free

And, they can also speed up development, because they can give you a clearer direction forward. Just like writing tests up front can help ensure you're only writing functions that actually solve your problems, writing types up front can ensure you're actually covering all of the surface area in a way that encourages callers to "fall into the pit of success".