DEV Community

Cover image for How TypeScript squashed all known bugs

How TypeScript squashed all known bugs

Matt Eland on September 22, 2019

You know that application that keeps you up at night hoping you won't have to change it? It seems like we all have one. Mine was in JavaScript. It...
Collapse
 
lampewebdev profile image
Michael "lampe" Lazarski

Besides the click bite title, I find the problems you're describing are not a thing that typescript itself is a solution too.

All of them are tooling and design problems.

  • Finding Existing 'Linking' Issues

    • This is solved by VSCode or Webstorm
    • You just have to use Import/Export's
  • Strongly-typed Variables

    • typeof is your friend here
    • Okay typeof has it strange behaviors
    • Also TypeScript also has its quirks here Promise<MyType<T>>. Is this more helpful maybe?
  • Catching silly mistakes with ESLint

    • Not related to Typescript
  • Introducing Classes

    • Not related to TypeScript
    • Putting everything into classes can also tend to code overhead and bad design and structure. Look at any more significant Java project
  • Eliminating Global State

    • Not related to TypeScript
    • Can be solved with ESlint
  • Testability

    • Not related to TypeScript
    • Testing is hard

In general, it sounds more like what the most significant difference here is that the team is more experienced and knows better what is needed. I'm not against TypeScript. It has its good things, but also it has its downsides. Like no abstract classes. Even OOP fanatics now say that composition is a better way then class inheritance (SOLID principle).

Collapse
 
adamant127 profile image
Adam Jones

Typescript adds expressive compile time type info. typeof doesn't compare. I think the main point was that the extra safety from types made the other refactoring possible. That's not surprising since types are basically a kind of formal proof of program code.

Collapse
 
blindfish3 profile image
Ben Calder

To say typeof doesn't compare is absurd. Compile-time type-checking definitely has its uses; but people seem to forget that (unless I am very much mistaken) no type checking is being carried by the compiled code at run time. In which case you absolutely must do type-checking on data coming from sources outside your application. Typescript is not a replacement for proper data validation for which typeof is pretty much essential.

Thread Thread
 
integerman profile image
Matt Eland

You are correct - TypeScript's checks are entirely at the transpilation level. You do occasionally need to do some checking at some boundaries, but things inside of your systems can generally be trusted to be properly typed if you have proper validation at the boundaries and rely on tsc to catch the other issues.

Thread Thread
 
blindfish3 profile image
Ben Calder

I am not mistaken. From Typescript design goals:

Non-goals

  • ...
  • Add or rely on run-time type information in programs, or emit different code based on the results of the type system. Instead, encourage programming patterns that do not require run-time metadata.
Thread Thread
 
integerman profile image
Matt Eland

I feel like you're really wanting to talk.

Collapse
 
itachiuchiha profile image
Itachi Uchiha • Edited

I still confused, for example, I create a method like this;

function aTypeScriptMethod(age: number) {

}

And backend data returns like that;

{
  name: 12,
  age: 'John'
}

This is wrong I know. But I just imagined.

I used this data like that;

let age = dataFromBackend.age
aTypeScriptMethod(age)

So, how can help us TypeScript in this case? I really don't have enough knowledge about TypeScript.

Collapse
 
olvnikon profile image
Vladimir

In the end, nobody replied to the question. You need to use a type guard for this. It is when static typing becomes dynamic. You have to manually check each field in the payload by typeof. Check the official docs.
typescriptlang.org/docs/handbook/a...

Collapse
 
owenpattison profile image
Owen Pattison

So your aTypeScriptMethod would have a strict typing of number which means it will only accept that type.

This means when you later set age from dataFromBackend.age the let would be cast as a string.

Therefore when you try to pass the function a string you would see a compilation error, that would give you feedback saying you have tried to pass a string to the method rather than a number resulting in your code not compiling until you resolve the casting of age.

Collapse
 
blindfish3 profile image
Ben Calder • Edited

Owen - Either I'm misinterpreting your answer or it is simply wrong. Typescript only does compile-time type-checking. All it knows about data coming from outside is what hypothetical type you have assigned to your input parameters; but no run-time type checking or data-validation is embedded into the compiled code that actually handles the data: it has been compiled to plain JavaScript with no type checking.

In the example given Typescript is no help at all: the application would simply crash. I've seen this happen recently in an application taking data from a PHP backend out of our control. The data didn't conform to the data type we expected and our application bombed because someone forgot to add the proper checks. This was in QA so no big deal; but could have been really problematic if it had slipped through the net.

I think it would be unfair to call this a flaw in Typescript; but it is really important that people understand this. Typescript is not a substitute for doing proper type-checking/validation on data that is outside your control.

Thread Thread
 
integerman profile image
Matt Eland

If that was to me, you need to read it in context.

tsc doesn't generate type checking logic, it does static tranpilation analysis based on what you've told it about the types. If you tell it the Web API result returns a number, it'll roll with it and find no issues (assuming you treat it like a number). Since it transpiles down to JavaScript, the variable will still get assigned a string and you get the same sort of an issue down the road. That's why it's important to get your type definitions correct as well as potentially validate them at the boundaries with a typeof check.

Also bear in mind union types and nullability are supported in TypeScript and should be considered and used. The benefits once you understand them are great, however.

Thread Thread
 
blindfish3 profile image
Ben Calder

Matt - my response saying the answer given was incorrect was not directed at you. I've edited it to make that clearer ;)

Collapse
 
seangwright profile image
Sean G. Wright

Great overview of the benefits of a type system (and bringing good design patterns) with an in-use code base.

Collapse
 
mmakrzem profile image
Marek Krzeminski

Could you share your eslint rules

Collapse
 
integerman profile image
Matt Eland

I unfortunately cannot share any code with this particular article due to shared ownership. Was there some specific aspect you're curious about? I could talk about that in more depth.

Collapse
 
mmakrzem profile image
Marek Krzeminski

I've been using typescript for about 2 years now and my lint rules are defined in tslint. I'm looking to convert everything over to eslint, so I'm curious to see what rules people are using. I am aware of airbnb rules but I'm interested in seeing what other things people typically lint