DEV Community

Cover image for I've been writing TypeScript without understanding it

I've been writing TypeScript without understanding it

vincanger on June 11, 2024

I admit, I don’t really understand TypeScript The other day, I was stuck with a bug in some code that was handling optimistic updates, s...
Collapse
 
brense profile image
Rense Bakker

It's worth noting that transpilation and compilation are not exactly the same thing. Transpilation is a style of compilation that translates code from one language into another. In typescript that's theoretically really simple because it is a superset of JavaScript. Presumably if you remove all type information from the typescript file, it could be run like a normal JavaScript file. This is not exactly the case, but you get the difference with a language like C that gets compiled into machine code. Transpilation is typically really fast, while compilation can take a little longer. There are actually several runtimes now (bun/deno) that can run typescript code directly, without any transpilation.

Collapse
 
vincanger profile image
vincanger

Oh nice. Thanks for the info. I wasn’t aware that bun and deno could do that!

Collapse
 
eshimischi profile image
eshimischi

Small correction about bun/deno. Both indeed execute TS without transpilation when do it directly, BUT if you launch your app in the browser they will use esbuild to transpile code into JS.

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇

That's because Deno and Bun are Runtime Environments for Javascript/Typescript.
If you want to run your app in Browser (which contains a different Runtime Environment) you need to give it what it supports (JS in this case).

I don't know what's the sense on using Deno or Bun if your target is the browser in the first place but here's the explanation.

Thread Thread
 
eshimischi profile image
eshimischi

To be clear, from Bun's documentation: "Bun natively supports TypeScript out of the box. All files are transpiled on the fly by Bun's fast native transpiler before being executed. Similar to other build tools, Bun does not perform typechecking; it simply removes type annotations from the file."

Thread Thread
 
joelbonetr profile image
JoelBonetR 🥇

Oh well, that's more lazy even, thank you for letting me know! <3

Collapse
 
webreflection profile image
Andrea Giammarchi • Edited

the article is nice but the satisfies looks like a non-sense to me ... in JS:

const a = { name: 'Bob', age: 12 };
const b = a;
b === a;
Object.is(b, a);
Enter fullscreen mode Exit fullscreen mode

A constant that points at another constant is the other constant itself. If b is exactly a it makes no sense that b satisfies Person but a does not satisfy Person, they are the exact same reference to the exact same pointer in memory.

I think this was a genuine mistake form TS itself and I get people trying hard to explain the difference but if JS is what matters at the end: there is no difference.

Specially with composition, I find extremely hard to also justify this:

// what does this do?
const a = {
  ...foreign,
  otherThing: 123
} satisfies Person;

// why is this fine?
const b = a satisfies Person;
Enter fullscreen mode Exit fullscreen mode

It looks like a limbo between casting where satisfies act like an enabler at distance but can't validate the "satisfaction" of the literal source of an object.

Once again, it's not about your post, rather about the fact you are giving for granted that satisfies behavior makes sense only because the master of TS or TS itself told you so ... I think they could've done a better job with a single keyword that is ambiguous for no reasons and it honestly makes zero sense at the JS level.

Collapse
 
jendoodle profile image
Jen Lewis

I agree, honestly the more I learn about TS the less it seems necessary. Just kind of seems like it's forcing Javascript to do something it wasn't designed to do.

Collapse
 
webreflection profile image
Andrea Giammarchi • Edited

that's where I'd draw a line between being a superset VS a shenanigans based logic ... luckily enough, I still don't need TS in my projects as they are all core JS enablers, no need for this mental muscles unnecessary overhead 🤷‍♂️

Collapse
 
michaelmior profile image
Michael Mior

Now, Let’s see how TypeScript inferred the types of the person properties:

TypeScript isn't really inferring anything here. You told TypeScript that the type of the properties should be either a string or a number :)

Collapse
 
vincanger profile image
vincanger

Yes, you're right. What I should have said is that typescript did not infer the narrower type I defined. :)

Collapse
 
daniel_nwokocha profile image
Daniel Nwokocha

Informative.
I also like your honest style of writing.

Collapse
 
vincanger profile image
vincanger

Thanks, Daniel.

Collapse
 
devvictory profile image
Karan Sethi

Thanks for sharing this! Admire your style of writing mate.

Collapse
 
pyprocrast profile image
Stevenr

TLDR- I’ve been writing every language without understanding it. 😂😂😂

Collapse
 
justaguyfrombr profile image
Misael Braga de Bitencourt

Typescript is a linter

Collapse
 
joelbonetr profile image
JoelBonetR 🥇

Just in the sense of static code analysis but the similarities end there. Sadly though 😅 If that were the case we wouldn't require ESLint and additional sh*tload of dependencies which would be nice

Collapse
 
robert_schaffrath_8fa02f5 profile image
Robert Schaffrath

With the Bun runtime, you can run TypeScript as is. No transpiling needed. Also runs CommonJS and ESmodules without special file name extensions.

Collapse
 
eshimischi profile image
eshimischi

Transpilation by bun or deno is happing when you launch your app in the browser.. because non of modern browsers know something about TS yet (i know that community is working on it)

Collapse
 
masteing_the_code profile image
Joel Jose

This is really good. I enjoyed the reading.

Collapse
 
vincanger profile image
vincanger

thanks!

Collapse
 
itsarun01 profile image
Arun kumar

Superb article

Collapse
 
litlyx profile image
Antonio | CEO at Litlyx.com

Great content! It brings real insight on real life!

Thank you!
Keep the great work up!

Antonio, CEO & Founder at Litlyx

Collapse
 
syedmuhammadaliraza profile image
Syed Muhammad Ali Raza

Good one with real life example

Collapse
 
mikhaelesa profile image
Mikhael Esa

This is a great one! Will definitely try the satisfies keyword. Thank you!

Collapse
 
alxwnth profile image
Alex

Nice post, thanks!

Collapse
 
devpugg profile image
Devpugg

Couple of things:

Transpilation is a made up new term, it's just compilation.
Compiling means parsing source code, building an AST and then generating some other source code. Usually, that's lower level code like Assembly, which can be used to produce machine code, but that's an implementation detail.
Some folks thought compiling higher level langs into other high level langs warranted a new term. Personally, I think it's just confusing, but whatever. Just wanted to point out there's nothing special about it.

The distinction between scripting and compiled langs is also a bit misleading. That X user, @yacineMTB, and this article seem to conflate scripting with interpreted, but that's not quite the same thing. It's even more confusing that he then asks for a binary, which is the result of compilation. So he's essentially asking about running a compiled language without compiling it and yet, somehow, magically, still have a binary. Makes no sense.
If you want to run a script, you typically use an interpreter, and you can do that for TS too, via Deno and Bun.

Which brings me to VMs. They don't generate machine code per se, in fact, the whole point is to avoid it. Again, that's a compiler's job. VMs instead take an AST and evaluate it, thereby skipping the code generation step.

Finally, type systems! TS's excess property checking is a semantic rule and not necessarily related to the Structural nature of the type system. It's more about subtyping, which granted, is more frequent in structural systems. A structural type system can still throw a type error in subtyping situations if the definition of type equality demands it.
For example, you could rule {foo: string} != { foo: string, bar: integer }. TS developers decided against it, and while that's a somewhat controversial decision, I personally think it was a good one given the nature of most JS codebases.
If you're interested, other languages, name Purescript and Elm, are far stricter on this and avoid subtyping, instead opting for something like row polymorphism or extensible records. That has its downsides too, though.

Collapse
 
michaelmior profile image
Michael Mior

Transpilation isn't really a "new term." Transpilers have been around since at least the mid-90s.

Collapse
 
ayush2390 profile image
Ayush Thakur

Quite an informative article

Collapse
 
vincanger profile image
vincanger

Thanks, glad you like it :)

Collapse
 
mirzalazuardi profile image
Mirzalazuardi Hermawan

Thanks for sharing your knowledge

Collapse
 
dtasev profile image
Dimitar

On a first look this is just a runtime type error waiting to happen...

What's the point of declaring a string | number when you know what the type is? The whole point is to show you the potential type error, and with satisfies you've not fixed the real issue, but hidden it.

If your variable can be more than one type and the function/property you're calling doesn't exist on all types then you will have to do type checks at runtime to avoid a runtime error anyways.

Collapse
 
alex_peirson_1aae004e1cfd profile image
Alex Peirson

Thanks for a great article! Like you I've been increasingly using TS but have realised that I don't truly understand it. This scenario where an object can have multiple keys of different types is something I run into all the time so am really grateful to learn about the satisfies keyword - thanks!

Collapse
 
dscheglov profile image
Dmytro Shchehlov

It seems the author is more interested in promoting their product than discussing TypeScript. It's just clickbait, nothing more ... unfortunatelly.

By the way, JavaScript has become a compiled language since the introduction of Just-In-Time (JIT) compilation in modern JavaScript engines like V8, which was introduced in 2008.

cabulous.medium.com/how-v8-javascr...

Collapse
 
matijasos profile image
Matija Sosic

Nice stuff! I think "transcompilation" is often referred to as "transpilation" - any difference between the two?

Collapse
 
michaelmior profile image
Michael Mior

They're the same thing although transpilation is the much more commonly used term.

Collapse
 
z2lai profile image
z2lai • Edited

Great topic! I never knew about this feature which seems to be an alternative to explicitly casting with "as".

However, everything starting from "Why is that? (when you were explaining the bug with intermediate variables) makes no sense. You mention it's a Javascript thing then you immediately introduce a TypeScript concept.

Excess property checking is actually the exception to the rule. TypeScript uses what’s called a “Structural Type System”. This is just a fancy way to say that if a value has all the expected properties, it will be used.

This paragraph was confusing, are we talking about excess property checking or structural type system and how is it an exception to what rule?

And lastly, your solution to the "bug" with satisfies is avoiding it altogether and going back to direct type annotation. But this brings us back to the original problem, so I'm actually unsure of what you're trying to say at the end.

My feedback is less about your technical knowledge but more about improving your thought process or paragraph structuring. I think it would help if you added a concluding sentence per paragraph that summarizes the point youre trying to make by tying the why and how back to the what, before jumping to the next paragraph. And on the same note, the entire article jumps all over the place from introducing the satisfies keyword, then to what is TypeScript, then to promoting your SaaS (please move this to the end), then back to the actual topic of the article.

Anyway, thank you for sharing and keep on writing and improving!

Collapse
 
infomiho profile image
Mihovil Ilakovac

Any good books to recommend on the topic?

Collapse
 
vincanger profile image
vincanger

I read a bit of Effective TypeScript for this article, along with some random blog articles

Collapse
 
rampa2510 profile image
RAM PANDEY

Things like these makes me want to steer away from Javascript. We have to do so many complex stuff just to fix a linter issue.