DEV Community ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป

Cover image for TypeScript vs JavaScript๐Ÿค”
Archit Sharma
Archit Sharma

Posted on

TypeScript vs JavaScript๐Ÿค”

NOTE: Debate on comment section

TypeScript vs JavaScript is one of the most controversial topics in tech.
Some developers prefer TypeScript because it offers static/strong typing, while others prefer JavaScript because it is less complex.
In this article, I will discuss my thoughts on this debate of which one is better than the other.

Typescript vs. Javascript

What is TypeScript?

TypeScript is an open-source programming language for developing large-level applications. TypeScript was developed by one of the tech giants - Microsoft, in 2012. The actual reason behind this TypeScript development was to handle large-scale applications.

TypeScript is also used by Angular, a JavaScript framework, for web development services. According to the report, TypeScript is already used by almost 60% of JavaScript developers, and another 22% want to deploy it.

So let's look at the advantages and drawbacks of TypeScript and see if it's worth adding not just on your own projects but also on bigger scale projects, and what it brings to the table.

TypeScript is a long-term investment; it takes time to learn and time to add things to your code, but if you accomplish both of those things, you'll start getting some very nice rewards from it, and I believe these rewards are worthwhile.

So lets take a look at the Advantages and Drawbacks of TypeScript.

Advantage of TypeScript over JavaScript

  1. TypeScript constantly highlights compilation errors throughout development. As a result, although JavaScript is an interpreted language, runtime errors are less common.

  2. TypeScript supports static/strong typing, whereas this is not in JavaScript.

  3. TypeScript runs on any browser or JavaScript engine.

  4. Excellent tools support, including IntelliSense, which offers active suggestions as code is added.

  5. It has a namespace concept by defining a module.

Drawbacks of TypeScript over JavaScript

  1. Generally, TypeScript takes time to compile the code.
  2. A compilation step is necessary to convert TypeScript into JavaScript if we want to run the TypeScript application in the browser.

Should I learn JavaScript or TypeScript?

Well, understanding TypeScript will be simple for you if you are familiar with JavaScript. The syntax and run-time behaviorย of both languages are identical.

Due to its popularity, JavaScript has a large development community and a lot of resources. Because both languages are frequently used in the same way, TypeScript developers may likewise take advantage of such resources.

Will TypeScript Replace JavaScript?

The best answer to the above question is NO, of course!

Speaking of TypeScript, it is a totally distinct language that only shares JavaScript's fundamental characteristics. JavaScript cannot and will not ever be replaced.

Conclusion

In the end, after going through all the insights we have curated in this article, we can say that both languages have advantages and drawbacks.

Developers that wish to write understandable, organised, and clean code should use TypeScript. Well, we are not mentioning what TypeScript offers are, including various live-bugs checking, and static typing.

Although JavaScript is not a comprehensive programming language, it can be used with HTML to improve the quality of web pages. Moreover, you will find many experienced developers who are proficient in JavaScript coding.

Despite not being a full-featured programming language, JavaScript may be used alongside HTML to enhance the quality of web pages. Additionally, you may discover a lot of seasoned engineers that are skilled at coding in JavaScript.

Thanks for reading this article, I know this is a debatable topic so I would love to here your point of view on comments. Do follow me for more content like this.

Whatโ€™s next?

  1. How JavaScript Works?
  2. The History of JavaScript
  3. You need to learn Kubernetes RIGHT NOW!!

Top comments (39)

Collapse
jonrandy profile image
Jon Randy • Edited on

TypeScript runs on any browser or JavaScript engine

Not really, it's compiled to JS first. You can't "run" TypeScript in a JS engine.

...including IntelliSense, which offers active suggestions as code is added.

This kind of thing is readily available for JS also.

It has a namespace concept by defining a module

Not entirely sure what you mean here, but modules are fully available natively in JS.

TypeScript does not support abstract classes

I'm not a TypeScript user, but some quick googling shows TypeScript does support abstract classes (apparently since 2015?). JS doesn't support them natively (but then again it doesn't really have classes either), but it's possible to code up something that works the same.

Collapse
fjones profile image
FJones

I'd also add that the intro is very reductionary:

others prefer JavaScript because it is less complex

I'm a strong proponent of JS over TS not because of TS complexity, but because of the lack of benefits at the cost of complexity. I can't recall the last time TypeScript would have prevented a bug on production, but I very much know how much longer it takes to write TS code. The usual counter to that is the IntelliSense assistance, which you've already shot down, but I would elaborate on a bit:
IDEs that derive data from static analysis of JS can provide nearly the same information (e.g. autocompletion) as from TypeScript. The small added information about type coherence can be achieved just as well through some framework features (React's proptypes), or Docblock-annotations. None of it requires TS. The overhead of writing and reading TS, however, is massive - especially for larger projects, where people seem to want TS as gospel.

The benefits of TS are almost always less than the drawbacks. When working with external data (e.g. API responses) it also gives a false sense of security, because the checks are at compile time, not runtime.

I advocate for TS on self-contained backends or on shared Fullstack applications - there, compile-time safety can be a very useful indicator - but client-side? I'll die on this hill: JS wins, every time.

Collapse
joelbonetr profile image
JoelBonetR

+1

Collapse
jonrandy profile image
Jon Randy

Totally agree

Collapse
iarchitsharma profile image
Archit Sharma Author

This kind of thing is readily available for JS also.

well it says including...

Not entirely sure what you mean here, but modules are fully available natively in JS.

In JavaScript there are no predefined methods to use namespaces.

Collapse
joelbonetr profile image
JoelBonetR • Edited on

Namespaces are a paradigm and not a "feature".

var truck= {
  start: function () {
    console.log("Truck in Started!");
  }
}

var bus = {
  start: function () {
    console.log("Bus is Started!");
  }
}
Enter fullscreen mode Exit fullscreen mode

Start method is scoped inside it's object (context).

truck.start(); // Truck in Started!
bus.start(); // Bus is Started!
Enter fullscreen mode Exit fullscreen mode
  • Namespace usage protects and isolates the code from other applications.
  • You can use multiple functions with the same name, then distinguish them by utilizing the JavaScript namespace like in the example above.
  • It becomes easier to recognize the variables and functions from where they are defined.

It's not the only way to reach that. Setting private functions for example, won't clash against other private ones so they are contextualized separatelly be they with the same name or not.
The difference with the namespaces are that you mark a data structure (Object) property as the method so you always call it through the instantiation object name plus the method name.

Collapse
jonrandy profile image
Jon Randy

If they both 'include' it, how is it an advantage?

Thread Thread
iarchitsharma profile image
Archit Sharma Author

Actually main point over here was -

Excellent tools support

Although I get it what you wanna say
Thanks for fact checking!

Collapse
josunlp profile image
Jonas Pfalzgraf • Edited on

Your first point is simply not true. New Engines like deno offer a runtime for direct TypeScript usage.

Collapse
peerreynders profile image
peerreynders
  1. The JavaScript engine is still V8 โ€” so it "runs" JavaScript
  2. For performance reasons TS is only transformed, not type checked, when it is initially loaded.

In my book that doesn't qualify as "runtime usage" but out of the box loading support.

What type of looks would you expect if you suggested to a software engineer to support an environment where C-source is compiled and linked to binary every time you need to execute the code even though the source code hasn't changed?

Thread Thread
josunlp profile image
Jonas Pfalzgraf

Technically, you are right. Still, this is what makes Deno so great. It's a runtime that on the fly uses your Typescript code without you being in the need to compile it yourself.

Thread Thread
peerreynders profile image
peerreynders • Edited on

Source code transformation shouldn't be a (production) runtime concernโ€ฆ

It's bad enough that JavaScript code has to make its way through Ignition, Sparkplug and Turbofan.

Thread Thread
josunlp profile image
Jonas Pfalzgraf

Typescript is a superset of JS. For an example C# code gets compiled into a inter language before then to bytecode. These two steps are necessary to ensure core features. Same goes for Typescript and JS. Since Javascript is the standard V8 can understand, Typescript gets compiled. This is why Runtimes like Bun and Deno with their build in Compile Support are great. They take the usual "watch and compile" Step away. Its just another step in the evolution of Code. If you want to use bytecode in the Browser, take a look at WebAssambly.

Thread Thread
peerreynders profile image
peerreynders • Edited on

Typescript is a superset of JS.

"TypeScript is a Subset of JavaScript

I can't impress this one enough. Technically it is a superset from a feature support perspective. However, people use it so they have compile-time type checking so once that becomes a requirement for you there are just things you can't do with TypeScript."

[The Trouble with TypeScript]

I came to that same conclusion before the article was published.


They take the usual "watch and compile" Step away. Its just another step in the evolution of Code.

It confuses design time and runtime; yet another concession to developer convenience (by developers nonetheless).


If you want to use bytecode in the Browser, take a look at WebAssembly.

Collapse
jonrandy profile image
Jon Randy

Then that is a TS runtime. OP refers to browsers and JS engines, which is what I was addressing.

Thread Thread
josunlp profile image
Jonas Pfalzgraf

Deno IS a JS runtime with full TS Support. For browsers, there are certain experiments, but nothing productive these days.

Collapse
bwca profile image
Volodymyr Yepishev

For me, the advantage of typescript is it's type system. As for js, you can write it without any tools and it will work. Doesn't have to be transpiled or bundled, very low learning curve, open browser console and you've got yourself a REPL.

Collapse
iarchitsharma profile image
Archit Sharma Author

Yup the type system in TypeScript really helps detecting errors at compile time and JavaScript isn't as complex as Typescript.

Collapse
joelbonetr profile image
JoelBonetR

Hybrid workaround ๐Ÿ˜

Collapse
bwca profile image
Volodymyr Yepishev

Aww... no generics or mapped types? :>

Thread Thread
peerreynders profile image
peerreynders • Edited on
/**
 * Factory for the core structure of a suite
 * @template {object} [U = Record<string,never>]
 * @param {import('./internal').State<U>} state
 * @returns {import('./internal').Context<U>}
 */
function context(state) {
  return {
    tests: [],
    before: [],
    after: [],
    bEach: [],
    aEach: [],
    only: [],
    skipped: 0,
    state,
  };
}
Enter fullscreen mode Exit fullscreen mode

Preact compat

Thread Thread
bwca profile image
Volodymyr Yepishev

Interesting, but can it do the heavy lifting ts does? I.e. generating a type containing all possible property paths for a nested object, i.e. like this?

Thread Thread
peerreynders profile image
peerreynders

Basically the types live in a TypeScript declaration file so it's just TypeScript.

Clean separation between type space (TypeScript) and value space (JavaScript).

With that setup it is now possible to only perform static type analysis on demand. In this case it's used to arrive at "well formed JavaScript" while keeping the source under developer control.

That said you can arrive at a similar TS workflow with vite. esbuild transforms TS "blazingly fast" without doing any type checking. So you can worry about tests first, types second.

Collapse
josunlp profile image
Jonas Pfalzgraf

For me, the whole concept of TypeScript feel so much more like working productively than JS. This might change with the recent developments in ES2022 and ES2023, since many of TypeScript's loved structures (sadly not the Type System) find their way into common JS syntax.

Collapse
peerreynders profile image
peerreynders

the whole concept of TypeScript feel so much more like working productively than JS

That's only half the story, the perspective of the application developer.

"Publishing an extensible package with good TS support is hellish."

Collapse
josunlp profile image
Jonas Pfalzgraf

And yes, from the perspective of a package developer

Collapse
josunlp profile image
Jonas Pfalzgraf

If you write your package in TS it's just super easy.

Thread Thread
peerreynders profile image
peerreynders

So writing Redux from scratch in TS would be easy?

Perhaps try it yourself and then maintain it long term to see if you can say that with a straight face.

Even maintainers of libraries written from scratch in TS report that types significantly increase their maintenance burden.


Learning and Using TypeScript as an App Dev and a Library Maintainer

Thread Thread
josunlp profile image
Jonas Pfalzgraf

The big problem most of the time is, that most developer's dont do a complete rework of the code. They built a js to TS support. Typescript uses different Development patterns then JS. So if you try and work your types alongside with your js code, yes its super messie and hard to maintain. For example Angular and Vue did that big step with a major release and rewrote the entire framework in TS

Thread Thread
peerreynders profile image
peerreynders

Typescript uses different Development patterns then JS.

If that were true, we could have had a much better language to begin with โ€ฆ like ReScript.

Unless of course your idea of better is "web development with C#".

"TypeScript began its life as an attempt to bring traditional object-oriented types to JavaScript so that the programmers at Microsoft could bring traditional object-oriented programs to the web."

[TypeScript for Functional Programmers]

Collapse
andrewbaisden profile image
Andrew Baisden

TypeScript decreased my anxiety but increased the time it takes to write code ๐Ÿ˜…

But it's worth it.

Collapse
natescode profile image
Nathan Hedglin

After doing a refactor on a large Javascript codebases, I'd die to have static typing just to refactor intelligently. Javascript refactoring is just find-and-replace like it is 2005.

Collapse
joelbonetr profile image
JoelBonetR • Edited on

Refactor means to change the implementation details without altering the behavior.

The only way to ensure the behavior is through tests, hence you need tests in order to Refactor, otherwise you're just "changing code".

Then, if the code is tested there's few benefit on static typing, and even less if your code is documented properly (so you can know what a function/method expects as parameters and what it will return by simply hovering your cursor over it's name).

Edit: I recommend the book Refactoring Javascript by Evan Burchard, it may bring some light to this topic.

Collapse
natescode profile image
Nathan Hedglin
  1. I know what refactoring is
  2. You're one of the more argumentative and cocky developers on here
  3. Why would I write tests for something I get for free?! You want to write more code that needs to constantly run and slow down development and the CI / CD pipeline?! That's way worse than a compiler checking types. I can only test what I know to test. Type checking checks everything consistently.

Tests validate implementation, types validate usage. They're opposites not enemies. You should know that.

At Best Buy I needed to change a method to take a third parameter. The compiler told me where to make the rest of the changes instantly. I was able to safely refactor 80+ locations. You would have been doing find and replace for quite awhile.

Thread Thread
peerreynders profile image
peerreynders

Tests validate implementation.

If they are doing that then they are a waste of time.

Microtests cannot "verify correctness". They are there to detect unwanted change in system behaviour which is exactly what you need when you refactor.

In 2014 James O. Coplien published Why Most Unit Testing is Waste (part 2). Michael Feathers responded with one of his earlier articles The Flawed Theory Behind Unit Testing (2008).

"Unit testing does not improve quality just by catching errors at the unit level. And, integration testing does not improve quality just by catching errors at the integration level. The truth is more subtle than that. Quality is a function of thought and reflection - precise thought and reflection."

In 1996 Extreme Programming (Kent Beck et al.) used unit tests as a design/development feedback tool. This formed the basis of the Classical/Inside Out/Bottom Up/Detroit/Chicago school of unit testing in 1999. The emergence of mocking libraries gave rise to the Mockist/Outside In/Top Down/London school of unit testing in 2000 shifting the focus towards "correctness".

These days people are trying to divine the purpose of microtesting from the capabilities of the prevalent tooling alone, concluding it's about "correctness"โ€”the original intent from 26 years ago has been all but lost.

Thread Thread
joelbonetr profile image
JoelBonetR

@natescode tests do not validate implementation details, tests validare behaviour, which is just what you want to avoid changing when refactoring.

By the ctrl+f thingy seems that the testing concept is not so clear and you still thing that refactor is just "changing code".

If you added a third parameter to a function chances are that the best option really was to split it instead or if you run against the clock simply set it as optional instead and mark it to refactor in the future ๐Ÿคท๐Ÿปโ€โ™€๏ธ

The reason for tests is not to add "correctness" bit to add confidence in the code which is something that types alone can't provide.

Thread Thread
natescode profile image
Nathan Hedglin

Testing doesn't catch this.

      add(true,3) // 4
Enter fullscreen mode Exit fullscreen mode

Actually writing tests to check argument types and quantities is wasting valuable development time. That isn't testing behavior but usage. Let the compiler do that faster and more consistently than a human can. Type validate grammar, Tests validate semantics.

One writes a unit test to make sure add, when given the right types, actually adds two numbers. Unit Tests validate behavior as you said.

  function add(a:number,b:number):number {
     return a + b 
 }

add(null, "3") // type error! We used the pre-defined function incorrectly. 
assert(add(1,2)).equals(3) // true. behavior / implementation is correct
Enter fullscreen mode Exit fullscreen mode

The above is returning the correct type and will make sure someone passes in numbers and not undefined or strings. It does NOT prevent invalid logic, which is what unit tests are for.

I could waste my and my team's time writing this garbage. Only 1 line actually adds the numbers.

 function add(a,b){
    // runtime type checking 
     let aIsValid = !Number.isNaN(Number.parseFloat(a))
     let bIsValid = !Number.isNaN(Number.parseFloat(b))
     if (aIsValid && bIsValid) {
       return a + b
     } 

    // error handling that a type checker could do for me
    if(!aIsValid) {
         if(!bIsValid){
          throw 'a and b aren't numbers!'
      }
       throw 'a is not a number!'
     } else {
      throw 'b is not a number!'
    } 
}

Enter fullscreen mode Exit fullscreen mode

Then the calling code will have to handle the possible thrown exceptions. But hey! I didn't have to write a few types and wait a few seconds for a compiler. Now the code is bloated, and slower.

'By the ctrl+f thingy seems that the testing concept is not so clear and you still thing that refactor is just "changing code".'

Nope, I know exactly what refactoring is. Here's a reminder.

"In computer programming and software design, code refactoring is the process of restructuring existing computer codeโ€”changing the factoringโ€”without changing its external behavior."

That is exactly what I was doing. I was adding cross-cutting concerns, tracing the flow of items in our Kafka queues. The external behavior did not change at all. All the existing tests passed.

"By the ctrl+f thingy seems that the testing concept is not so clear"

Nope, it seems your concept of static type checking isn't clear. I can refactor a type's name in a huge code base, even if there are other types, functions, comments etc with the same name. You'd have to find and replace and then do a bunch of regression testing. You're just treating your code like text. I'm treating my code like a data-structure.

"The reason for tests is not to add "correctness" bit to add confidence in the code which is something that types alone can't provide."

Correct! 100% agree here. I wrote tests at Best Buy too. Spending hours writing tests didn't help me safely refactor code, especially if the new requirements invalidate the assumptions in the existing tests. It doesn't help all the low skill developers use my code correctly either. They can't write tests to make sure they're using a function correctly, when they don't know how to use it correctly in the first place.

No sane person writes tests to make sure the correct types and number of arguments are correct, let a type checker do that for you. The type checker will never be wrong, a human will be.

Tests validate behavior (logic), types validate usage (grammar). They're both valuable and not mutually exclusive whatsoever.

Anyways, thanks for the debate. Have a great weekend.

Thread Thread
joelbonetr profile image
JoelBonetR

Hi Nathan, I agree mostly with this, types are extra safety you add into the code at a cost of some burden in maintenance.

The issue comes with code like that

  function add(a:number,b:number):number {
     return a + b 
 }
Enter fullscreen mode Exit fullscreen mode

You've a sense of calm and safety because you added :number but we all know that contextual information about types is removed during compilation because we compile to pure JavaScript, which doesnโ€™t know the types at runtime.
This behavior does not provide any kind of safety mechanism against incorrect or invalid inputs, such as inputs from unhandled API endpoints, libs, form inputs...
TypeScript is not designed to provide input constraints that are at an advanced level of type safety.

You can add type guards, validation libraries or manual checks in critical paths, of course (so you can in JS, see (prop-types)[npmjs.com/package/prop-types] or (Joi)[npmjs.com/package/joi] as examples).

Another way to workaround that is simply to (avoid runtime errors)[softwareengineering.stackexchange....].

const add = (...args) => args.reduce((p, c) => (Number.parseFloat(p) || 0) + (Number.parseFloat(c) || 0));

add(true, 3) // 3
add(false, 3) // 3
add('hey', 3) // 3
add('hey', true) // 0
Enter fullscreen mode Exit fullscreen mode

You can do the same with TS as well of course.
While 0 may represent a wrong result in this case

add(1, -1) // 0
add('hey', true) // 0
Enter fullscreen mode Exit fullscreen mode

You may either design it on a way it's not important or return an arbitrary value that you can check in the caller or keep bubbling the "wrong value" if the path is not critical (i.e. does not alter business logic, doesn't have side-effects and so on).

On the tests thingy... While type check tests are considered trivial for static typed languages in some codebases, my experience (and probably yours as well) says that runtime errors/exceptions due to wrong types happen either be JS, TS, Java... so maybe they are not so trivial at the end.

Both things together (static type checks and unit tests) are a win-win in code confidence terms. If you're not ensuring types in tests (overall) maybe consider adding them through paths that are dependant on third parties or other repos just in case.

Collapse
decker67 profile image
decker

Are you kidding with

not being a full-featured programming language

What is missing?

At least this post is not a deep comparison.

๐ŸŒš Friends don't let friends browse without dark mode.

Sorry, it's true.