HomeVideos

99% of Developers Don't Get Transpilers

Now Playing

99% of Developers Don't Get Transpilers

Transcript

352 segments

0:00

Transpilers is a concept that most

0:02

developers fail to understand. They

0:04

think it's black magic that turns

0:06

TypeScript into JavaScript or they treat

0:08

tools like Babel and SWC as black boxes.

0:11

In the next 10 minutes, we're going to

0:12

unpack abstract syntax trees, reverse

0:15

engineer how JSX becomes JavaScript, and

0:17

finally understand the difference

0:19

between a transpiler, a compiler, and an

0:21

interpreter. Let's dive in. A transpiler

0:24

is a special kind of compiler that

0:26

translates source code from one highle

0:28

language to another high-le language,

0:30

usually while preserving the original

0:32

program's intent and structure. The key

0:34

idea is that the output is still human

0:36

readable source code, not machine code

0:38

or bite code. At a conceptual level, a

0:41

transpiler exists to bridge a gap

0:43

between how developers want to write

0:44

code and what a target platform actually

0:47

understands. Transpilers allow

0:48

developers to use modern or more

0:50

expressive language features like those

0:52

in Typescript, Babel for JavaScript, or

0:54

CoffeeScript that the target environment

0:57

such as an older web browser or specific

0:59

JavaScript engine might not natively

1:01

support. Developers can write code using

1:03

preferred syntax, newer standards,

1:05

ECMAScript 2015 plus features, or higher

1:08

level abstractions, while the transpiler

1:10

ensures the resulting output is

1:11

compatible with the required often older

1:13

or more constrained target platform.

1:16

Let's talk about transpilers versus

1:18

compilers and interpreters. A

1:20

traditional compiler typically takes

1:21

source code and emits low-level output

1:23

like machine code or an intermediate

1:25

form such as bite code. An interpreter

1:28

executes programs by directly evaluating

1:30

source code or more commonly in modern

1:32

systems by executing bite code produced

1:34

by an earlier compilation step. In

1:37

practice, most interpreters are hybrid

1:39

systems that parse source code into an

1:41

intermediate representation and then

1:43

interpret or jit compile that

1:44

representation at runtime. A transpiler

1:47

sits in between. Like a compiler, it

1:49

performs parsing, semantic analysis, and

1:52

structured transformations. But instead

1:54

of lowering the program into machine

1:56

code or bite code, it lowers it into

1:58

another source language. So the output

2:00

is kept at a similar level of

2:02

abstraction. The output is intended to

2:04

be consumed by a separate compiler,

2:06

interpreter, or runtime. For example,

2:09

JavaScript emitted by a transpiler is

2:11

later parsed, optimized, and often JIT

2:13

compiled by a browser's JavaScript

2:15

engine. The key distinction is not how

2:17

much analysis is done, but what

2:19

abstraction level the output targets.

2:21

Compilers target execution. Interpreters

2:24

target evaluation. Transpilers target

2:27

compatibility and language translation.

2:30

Modern programming environments

2:31

sometimes blur these lines. For example,

2:34

JIT compilers. They combine both

2:35

interpreting code initially and then

2:37

compiling hot sections to machine code

2:39

for speed and hybrid models. Languages

2:41

like Java are compiled to bite code, a

2:43

form of compilation, and then

2:45

interpreted by a virtual machine. Now,

2:47

how do transpilers actually work under

2:49

the hood? Internally, a transpiler is

2:51

best understood as a treeto-tree

2:53

transformation system with compiler

2:55

discipline. Everything revolves around

2:57

the abstract syntax tree, not text. Once

3:00

source code is parsed, formatting and

3:02

surface syntax mostly disappear. What

3:05

remains is a structural model of the

3:07

program. The process begins with parsing

3:09

into an abstract syntax tree or a using

3:12

the source language grammar. Operator

3:14

precedence, associivity, and syntactic

3:16

structure are resolved here. At this

3:18

point, the transpiler is not thinking

3:20

about compatibility or lowering yet. It

3:23

is only constructing a faithful

3:24

representation of the program. Next

3:27

comes scope and binding resolution.

3:29

Identifiers are linked to their

3:31

declarations. Lexical scopes are

3:33

constructed and shadowing is made

3:35

explicit. This step is important.

3:37

Transformations that look trivial at the

3:39

syntax level can break program behavior

3:41

if scoping rules are misunderstood. For

3:43

example, rewriting block scoped

3:45

variables requires precise knowledge of

3:47

closure boundaries and lifetime

3:49

semantics. The core of the transpiler is

3:52

a transformation pipeline composed of

3:54

multiple passes. Each pass targets a

3:57

specific language feature and rewrites

3:59

it into more primitive constructs. These

4:02

passes pattern match on a nodes and

4:04

replace them with equivalent sub trees.

4:06

A single feature may go through several

4:08

stages. The ordering of these passes

4:10

matters because earlier transformations

4:12

often introduce structures that later

4:14

passes must understand. This is how

4:17

modern transpilers like Babel,

4:18

TypeScript or SWC function. They use

4:21

this pipeline of transformation passes

4:24

that traverse and modify the abstract

4:26

syntax tree. Breaking down complex

4:28

syntax into smaller backward compatible

4:30

code. The pipeline ensures that highle

4:32

features such as await often lowered to

4:34

generators or ES6 classes are

4:37

systematically reduced to more

4:38

fundamental constructs like state

4:40

machines or ES5 functions in a specific

4:43

order. Each pass reduces the program

4:45

toward a smaller, more restricted subset

4:47

of the target language. Mature

4:49

transpilers define a lowest common

4:51

denominator language level and guarantee

4:53

that all inputs eventually converge to

4:55

it. When the target language lacks

4:57

certain semantics, the transpiler

4:58

injects runtime helpers. These are small

5:01

support functions that emulate behavior

5:03

such as inheritance, iteration

5:05

protocols, or private fields. At this

5:07

stage, transpilers begin to resemble

5:09

runtime systems. Correctness now depends

5:11

not only on the transformation logic but

5:14

also on the behavior of these helpers.

5:16

Finally, the transformed a is printed

5:18

back into source code. The code

5:20

generator must reconstruct valid syntax,

5:23

manage parentheses and precedents and

5:25

often balance readability against output

5:27

size. Source maps are emitted alongside

5:29

the output so runtime errors can be

5:31

traced back to the original source code.

5:34

What makes transpilers uniquely

5:35

difficult is that they must preserve

5:37

observable behavior across real

5:39

runtimes, not just theoretical

5:41

semantics. This means modeling

5:42

evaluation order, shortcircuiting,

5:45

hoisting rules, and even long-standing

5:46

platform quirks. In practice, a

5:48

transpiler is less about syntax

5:50

rewriting and more about encoding a deep

5:52

executable understanding of language

5:54

semantics and compatibility boundaries.

5:56

So, while the transpiler ensures your

5:58

code syntax works in older browsers, it

6:00

doesn't guarantee your actual features

6:02

are working for users. To ensure your

6:04

application flows are solid without

6:06

spending all day rewriting your test

6:08

suite, check out today's sponsor, QA

6:10

Tech. QA Tech is an AI testing tool for

6:12

QA automation that uses agents to test

6:15

your product like a real user. goal

6:17

oriented, relying on UI behavior rather

6:20

than brittle scripts or selectors. The

6:22

AI explores your product and generates

6:24

new test cases to build your test suite.

6:26

It navigates beyond predefined paths,

6:28

catching functional and non-functional

6:29

regressions that scripted tests often

6:32

miss. QA plugs into your existing

6:34

infrastructure. Just point an agent at

6:36

your environment to run exploratory

6:38

tests or validate changes directly in

6:40

PRs and CI. Instead of binary pass or

6:43

fail results, you get qualitative

6:45

feedback and an actionable list of

6:46

issues to fix complete with the logs and

6:49

screen recordings. The biggest pain with

6:51

end to end is usually maintenance.

6:52

Right? With QA tests adapt as your

6:55

product evolves. When the UI or flows

6:58

change, the AI updates existing steps or

7:00

suggests new coverage to keep critical

7:02

user journeys protected. That means no

7:04

flaky tests and far less time spent

7:06

fixing broken automation. QA Tech is

7:08

built to provide your team with

7:10

continuous feedback via integrations

7:11

with GitHub, GitLab, Slack, and CI/CD

7:14

pipelines so you can trigger test runs

7:16

when and how you need. Check out QA Tech

7:19

using the link in the description to

7:20

start automating your tests with AI

7:22

today. Now, back to the video. One of

7:24

the most well-known transpilers is

7:26

Babel. It translates modern JavaScript

7:28

and JSX into older JavaScript versions.

7:31

Features like arrow functions or let and

7:33

const are rewritten into function

7:35

expressions and var often with helper

7:37

code injected to preserve semantics.

7:39

TypeScript is another example.

7:41

TypeScript adds a static type system and

7:43

additional syntax on top of JavaScript.

7:46

The TypeScript compiler strips away type

7:48

annotations and emits plain JavaScript.

7:50

In this sense, it is a transpiler from

7:52

TypeScript to JavaScript. Even though it

7:54

is often called a compiler, coffecript

7:57

provides a concise Ruby or Python

7:59

inspired syntax using indentation and

8:01

implicit returns that compiles to

8:03

JavaScript. It focuses on developer

8:05

ergonomics by reducing verbosity and

8:07

improving readability compared to

8:09

traditional JavaScript. Although it maps

8:11

closely to JavaScript rather than

8:12

ignoring compatibility. Tools like

8:14

mcripton using LLVM translate C or C++

8:18

into web assembly or JavaScript allowing

8:20

near native performance for complex

8:22

applications on the web. The line

8:24

between a transpiler source to source

8:26

and a traditional compiler source to

8:28

machine code does blur in these cases

8:30

because the output is often highly

8:32

optimized low-level code that is not

8:34

intended to be read or maintained by

8:36

humans. similar to assembly code rather

8:38

than just cleaner source code. Why do

8:40

transpilers exist? Transpilers exist

8:43

because language evolution and platform

8:45

deployment operate on different

8:47

timelines. Language designers can add

8:49

features quickly, but runtimes,

8:51

operating systems, embedded

8:52

environments, and browsers upgrade

8:54

slowly, unevenly, or not at all. A

8:56

transpiler decouples these timelines by

8:58

allowing new language constructs to be

9:00

expressed in terms of older already

9:02

deployed capabilities. In large

9:04

ecosystems, backward compatibility is

9:06

often non-negotiable. Enterprises may be

9:08

locked to specific runtime versions.

9:10

Embedded systems may never receive

9:12

updates, and browsers must support

9:14

legacy code indefinitely. Transpilers

9:16

allow developers to write modern

9:18

expressive code without forcing every

9:19

consumer of that code to upgrade their

9:21

execution environment. Transpilers also

9:24

exist to manage semantic complexity at

9:26

scale. As languages grow, features like

9:28

async control flow, advanced type

9:31

systems, and new module semantics

9:32

introduce behavior that is difficult to

9:34

reason about directly. By lowering these

9:37

features into simpler constructs,

9:38

transpilers make the runtime execution

9:40

model more explicit and predictable,

9:43

even if the source language remains high

9:45

level. Another major driver is tooling

9:47

and ecosystem leverage. by transpiling

9:49

into an existing widely supported

9:51

language. New languages inherit

9:53

debuggers, profilers, llinters, build

9:55

systems, and deployment pipelines for

9:57

free. This is why many experimental or

10:00

domain specific languages target

10:01

JavaScript, the JVM, or existing

10:04

scripting languages instead of building

10:06

new runtimes. A useful mental model is

10:08

to think of a transpiler as a

10:10

large-scale dshugaring engine. Many

10:12

language features exist to improve

10:14

expressiveness, not power. A transpiler

10:16

removes that sugar and expresses

10:18

everything in terms of simpler

10:20

constructs. A for of loop becomes an

10:22

explicit iterator protocol loop. The

10:24

target language already has the

10:26

expressive power. The transpiler just

10:28

makes the control flow explicit. A sync

10:30

await becomes promise chains or a state

10:33

machine. Unfortunately, translation is

10:35

not free. Generated code can be harder

10:37

to read, debug, and optimize. Source

10:40

maps are essential to maintain developer

10:42

ergonomics. There are also semantic edge

10:44

cases. When the target runtime does not

10:46

perfectly match the source language's

10:48

behavior, transpilers must compensate

10:50

with helpers or polyfills, increasing

10:52

complexity and bundle size. Polyfills

10:54

are just pieces of code that provide

10:56

modern functionality to older JavaScript

10:58

environments that do not natively

11:00

support those features. Polyfills run at

11:02

runtime in the browser, while

11:03

transpiling occurs at buildtime before

11:06

deployment. So transpiling converts

11:08

modern syntax into older compatible

11:10

syntax while polyfilling adds missing

11:12

built-in features such as APIs or

11:14

methods to older environments. For

11:16

example, converting an arrow function in

11:18

ES6 into a traditional function

11:20

expression would be considered

11:21

transpiling while mimicking missing APIs

11:23

such as promise fetch

11:25

array.prototype.includes

11:27

or math.runk using existing older

11:29

JavaScript capabilities is considered

11:31

polyfilling. Most importantly,

11:33

transpilers cannot transcend fundamental

11:35

platform limitations. They work best

11:37

when the target language is at least as

11:39

expressive as the source. Now, here's

11:42

the bigger picture. At a deeper level,

11:44

transpilers separate language evolution

11:46

from platform adoption. They enable

11:48

developers to write code using

11:50

future-facing abstractions while still

11:52

targeting present-day runtimes. If you

11:54

want to begin your journey in becoming a

11:56

10x engineer, I highly recommend

11:57

checking out codec crafters down below.

11:59

You can learn how to build Docker,

12:00

Reddus, Git compilers, and other

12:02

developer tooling from scratch. They are

12:04

hands down the best project-based coding

12:06

platform out there. So, do give their

12:08

platform a try. As always, thank you

12:10

very much for watching this video and

12:12

happy coding.

Interactive Summary

This video explores the concept of transpilers, distinguishing them from traditional compilers and interpreters. It explains how transpilers like Babel and TypeScript act as source-to-source translation tools that allow developers to use modern language features while maintaining compatibility with older target environments. The video details the technical process under the hood, covering abstract syntax tree transformations, parsing, scoping, and the use of runtime helpers. It also clarifies the difference between transpiling and polyfilling, and highlights why transpilers are essential for decoupling language evolution from platform adoption.

Suggested questions

3 ready-made prompts