JavaScript vs TypeScript: What’s the Difference?

JavaScript vs TypeScript: What’s the Difference?

JavaScript has one famous weakness. It will let you call a function with the wrong kind of value, and it will not complain until that value causes a problem at runtime — often in production, often three screens away from where the mistake was made.

TypeScript exists to fix exactly that. It adds a type system on top of JavaScript that checks your code while you write it, catching whole categories of bugs before the program ever runs. Then it erases those types and produces plain JavaScript, so what ships to the browser is unchanged.

This guide covers what each language is, how the type system works, what TypeScript actually catches, when it is worth the setup cost, and how to move a JavaScript project to TypeScript without a rewrite.

In one sentence: TypeScript is JavaScript with static types — it checks your code while you write it, then compiles down to plain JavaScript that runs anywhere JavaScript runs.

The Short Answer

The relationship between the two languages is not “old versus new” or “one replaces the other.” It is a superset relationship, and that single fact explains almost everything else.

JavaScript

The runtime language

Runs directly in browsers and in Node.js. No build step required.

Types are checked at runtime, if at all — and usually they are not.

VS

TypeScript

JavaScript plus types

Never runs directly. Compiled to JavaScript first, then executed.

Types are checked at compile time, before the code ever runs.

The practical consequence: every valid JavaScript file is already a valid TypeScript file. If you rename app.js to app.ts, it compiles and runs identically. TypeScript does not reject JavaScript — it accepts all of it, and gives you the option to add types on top.

A superset, not a replacement

TypeScript is maintained by Microsoft and released as an open-source compiler. It is not a fork of JavaScript or a competing language — it is a type checker layered over the language you already know.

JavaScript in One Paragraph

JavaScript is the programming language that runs in the browser. It is dynamically typed, which means a variable can hold a number now and a string later, and the language will not object. Types exist at runtime — the value 42 knows it is a number — but nothing checks that you are using it correctly before the program runs.

// JavaScript — no type annotations, no compile-time checking

function add(a, b) {
    return a + b;
}

add(2, 3);        // 5      — what you intended
add('2', 3);      // '23'   — no error, just wrong
add(2);           // NaN    — no error, just wrong

All three calls run without complaint. The second one returns the string "23" because JavaScript converts the number to a string when one operand is a string. The third returns NaN because 2 + undefined is not a number. Neither throws. Neither warns. The bug travels silently until it reaches something that breaks.

Dynamic typing is flexible and dangerous

The same flexibility that makes JavaScript pleasant for small scripts makes it fragile for large applications. A typo in a property name, a wrong argument order, a missing null check — all of them pass silently.

TypeScript in One Paragraph

TypeScript adds a static type system to JavaScript. You annotate what kinds of values your functions accept and return, and the compiler checks those annotations before the code runs. If you call a function with the wrong type, you get an error in your editor immediately — not a bug report next week.

// TypeScript — the same function, with types

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

add(2, 3);        // 5      — fine
add('2', 3);      // ❌ Error: Argument of type 'string'
                  //    is not assignable to parameter
                  //    of type 'number'.
add(2);           // ❌ Error: Expected 2 arguments,
                  //    but got 1.

Both of the broken calls are caught in the editor, before anything runs. That is the entire value proposition, and it applies everywhere: function arguments, object shapes, array contents, return values, and null checks.

What the compiler produces

Once the types have been checked, the compiler strips them out. The JavaScript that actually runs is identical to what you would have written by hand.

TS Your source
The file you write app.ts — JavaScript with type annotations, interfaces, and other TypeScript-only syntax.
tsc Compiler
Type checking happens here The compiler reads every file, checks every annotation, and reports errors. If there are no errors, it continues.
JS Output
Plain JavaScript, types removed app.js — the same logic, with every : number, interface, and type deleted. This is what the browser runs.
Types leave no trace

Nothing from the type system survives into the JavaScript output. Not the annotations, not the interfaces, not the type aliases. There is zero runtime cost in production.

The Same Function in Both Languages

Here is a small, complete example — a function that formats a user’s name — written first in JavaScript, then in TypeScript. The logic is identical. The difference is what each version tells the compiler, and what the compiler can then catch.

JavaScript version

function formatUser(user) {
    return {
        name: user.firstName + ' ' + user.lastName,
        email: user.email.toLowerCase(),
        isAdmin: user.role === 'admin'
    };
}

// Nothing here is checked.
// If user has no email, this throws at runtime.
// If user.firstName is a number, this silently produces garbage.
formatUser({ firstName: 'Ada', lastName: 'Lovelace', email: 'ADA@X.COM', role: 'admin' });

TypeScript version

interface User {
    firstName: string;
    lastName: string;
    email: string;
    role: 'admin' | 'editor' | 'viewer';
}

interface FormattedUser {
    name: string;
    email: string;
    isAdmin: boolean;
}

function formatUser(user: User): FormattedUser {
    return {
        name: user.firstName + ' ' + user.lastName,
        email: user.email.toLowerCase(),
        isAdmin: user.role === 'admin'
    };
}

The TypeScript version is nine lines longer, and in exchange it checks four things before the code ever runs:

  • Every property exists. user.firstName is valid — user.firstname is an error.
  • Every property has the right type. Passing a number as firstName is an error.
  • The role is one of three values. 'admin', 'editor', or 'viewer' — nothing else compiles.
  • The return value matches. If you forget to return isAdmin, the compiler objects.
Types as documentation

The User interface is also the clearest possible documentation of what a user is. A new developer opening that file knows the exact shape of the data without reading the implementation or digging through a database schema.

What TypeScript Catches

The most convincing argument for TypeScript is the class of bugs it eliminates. Here is the same buggy code in both languages, side by side.

JavaScript — silent and wrong
function getDiscount(price, rate) { return price * (1 - rate); } getDiscount('99.99', 0.2); // "79.992" — a string! // No error. This value flows // through the rest of the program // until something breaks, // usually much later.
Result: no warning. The function returns a string and the bug surfaces somewhere else, far from the cause.
TypeScript — caught immediately
function getDiscount(price: number, rate: number): number { return price * (1 - rate); } getDiscount('99.99', 0.2); // ❌ Error: Argument of type 'string' // is not assignable to parameter // of type 'number'.
Result: the editor underlines the argument in red. The code never runs, and the bug never ships.

The categories of bugs TypeScript eliminates

Typos in property names

Accessing user.emial instead of user.email is an error, not undefined.

Wrong argument types

Passing a string where a number is expected is caught before the code runs.

Missing arguments

Calling a function with too few arguments is an error, not a silent undefined.

Null and undefined access

With strictNullChecks, reading a property off a possibly-null value is caught.

Wrong return types

A function declared to return a number cannot accidentally return a string.

Impossible states

Union types make 'pending' | 'done' exhaustive — no other value can slip through.

Unhandled cases

Adding a new variant to a union causes a compile error everywhere you forgot to handle it.

Bad refactors

Renaming a property is checked across the whole codebase — no forgotten call sites.

TypeScript does not catch everything

It catches type errors, not logic errors. A function that adds when it should subtract compiles perfectly in both languages. TypeScript reduces the surface area of bugs — it does not eliminate them.

The Type System in Practice

TypeScript’s type system goes well beyond “this is a string.” These are the features you will use most.

Primitive types

const name: string  = 'Ada';
const age: number   = 36;
const active: boolean = true;

// Arrays
const scores: number[] = [90, 85, 72];
const names: string[] = ['Ada', 'Grace'];    // or Array<string>

// Tuples — fixed length, fixed types
const point: [number, number] = [10, 20];

Interfaces and type aliases

Both describe the shape of an object. interface is preferred for object shapes because it can be extended; type is more flexible and can also describe unions and primitives.

interface Product {
    id: number;
    name: string;
    price: number;
    tags?: string[];      // optional — the ? makes it optional
}

// Extending an interface
interface DiscountedProduct extends Product {
    discountPercent: number;
}

// A type alias for a union
type Status = 'pending' | 'shipped' | 'delivered';

// A type alias for an object
type Point = { x: number; y: number };

Union types — the most useful feature

A union says a value can be one of several things. Combined with a narrowed check, it makes impossible states genuinely impossible.

type Status = 'pending' | 'shipped' | 'delivered';

function describe(status: Status): string {
    switch (status) {
        case 'pending':   return 'Waiting to ship';
        case 'shipped':   return 'On the way';
        case 'delivered': return 'Arrived';
    }
}

describe('shipped');    // fine
describe('canceled');   // ❌ Error: not one of the allowed values

// Add a new status to the union and TypeScript will flag
// every switch statement that does not handle it.

Generics — types that take types

A generic lets a function or type work with many different types while keeping the relationship between them.

// Without generics, you would need `any` and lose all checking
function first<T>(items: T[]): T | undefined {
    return items[0];
}

first([1, 2, 3]);           // type: number | undefined
first(['a', 'b']);          // type: string | undefined

// The type is inferred from what you pass in,
// and the return type follows it exactly.
  • interface — describes the shape of an object. Preferred for objects and anything that might be extended later.
  • type — an alias for any type, including unions, intersections, tuples, and primitives.
  • enum — a named set of constants. Useful, but many teams prefer union types instead because they produce simpler JavaScript.
  • generic — a type parameter, written <T>, that lets a function or type work with many types while preserving the relationship between them.
  • Let inference do the work

    You do not need to annotate everything. TypeScript infers types from the values you assign, so const name = 'Ada' is already known to be a string. Annotate function parameters and return types; let everything else be inferred.

    Beyond Types: What Else TypeScript Adds

    The type system is the headline feature, but it unlocks a set of tooling improvements that matter just as much on a real project.

    Autocomplete that knows your code

    Type a dot after an object and your editor lists every valid property — with their types.

    Errors as you type

    Mistakes appear underlined in the editor, before you save, before you run, before you commit.

    Safe refactoring

    Rename a property and the editor updates every usage — or tells you which ones it cannot.

    Jump to definition

    Click a function and go straight to where it is defined, even across files and packages.

    Inline documentation

    Hover over anything to see its type signature and any doc comments attached to it.

    Self-documenting APIs

    A typed function signature tells the next developer exactly what it accepts and returns.

    Safer collaboration

    A shared type is a contract. Change it and the compiler tells every consumer.

    Gradual adoption

    You can add TypeScript to one file at a time, without rewriting the project.

    The tooling is the argument

    Ask experienced TypeScript developers why they use it and most will mention autocomplete and refactoring before they mention bug prevention. The type checker is what makes the editor smart.

    How TypeScript Runs

    Browsers and Node.js do not understand TypeScript. Every .ts file has to be converted to .js before anything can execute it.

    Write .ts
    →
    tsc checks types
    →
    Types stripped
    →
    Output .js
    →
    Browser runs it

    Setting up a project

    TypeScript installs as an npm package. The tsconfig.json file controls how it behaves.

    // Install TypeScript in a project
    // npm install --save-dev typescript
    
    // Create a tsconfig.json with sensible defaults
    // npx tsc --init
    my-project/ ├── src/ │ ├── app.ts ← TypeScript source │ └── utils.ts ├── dist/ │ └── app.js ← compiled output ├── tsconfig.json ← compiler configuration └── package.json

    A minimal tsconfig.json

    {
        "compilerOptions": {
            "target": "ES2022",
            "module": "ESNext",
            "strict": true,
            "outDir": "./dist",
            "rootDir": "./src",
            "sourceMap": true
        },
        "include": ["src/**/*"]
    }

    The strict flag is the one that matters most. It turns on several checks at once, including strictNullChecks — which is what makes null and undefined explicit rather than silently allowed.

    Modern build tools

    The tsc compiler is the official tool, but most projects use a bundler that handles TypeScript alongside everything else.

    Tools that compile or transpile TypeScript
    Tool What it does Typical use
    tsc The official TypeScript compiler Type checking, and compiling for Node.js projects
    Vite Dev server and bundler with built-in TS support Modern front-end projects, React, Vue
    esbuild Extremely fast transpiler Bundling and transpiling, often behind Vite
    SWC Fast Rust-based transpiler Next.js and other frameworks
    ts-node / tsx Run TypeScript directly in Node.js Scripts, CLI tools, quick experiments
    Transpiling is not type checking

    Tools like esbuild and SWC strip types extremely fast, but they do not check them. That is why most projects run tsc --noEmit separately as part of CI — the fast tool builds, and the type checker verifies.

    JavaScript Still Runs Everything

    It is worth being very clear about this, because it confuses a lot of beginners: the JavaScript you write in TypeScript is still JavaScript. The types are not a runtime feature.

    Here is a live example. This is plain JavaScript running in a browser, doing exactly what it would do if it had been written in TypeScript and compiled.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>What TypeScript Compiles To</title>
        <style>
            body {
                font-family: system-ui, sans-serif;
                padding: 28px;
                background: #f8fafc;
                margin: 0;
                color: #0f172a;
            }
            h2 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.08em; color: #64748b; margin: 0 0 12px; }
            .row {
                background: #fff;
                border: 1px solid #e2e8f0;
                border-radius: 10px;
                padding: 12px 16px;
                margin-bottom: 8px;
                font-family: ui-monospace, monospace;
                font-size: 13px;
                display: flex;
                justify-content: space-between;
                gap: 12px;
            }
            .label { color: #64748b; }
            .value { color: #0891b2; font-weight: 700; }
        </style>
    </head>
    <body>
    
        <h2>The compiled output</h2>
        <div id="output"></div>
    
        <script>
            // This is the JavaScript that a TypeScript compiler
            // produces from a typed function. Notice:
            // — no type annotations remain
            // — no interface exists at runtime
            // — the logic is exactly what you wrote
    
            function add(a, b) {
                return a + b;
            }
    
            function formatUser(user) {
                return {
                    name: user.firstName + ' ' + user.lastName,
                    email: user.email.toLowerCase(),
                    isAdmin: user.role === 'admin'
                };
            }
    
            const user = {
                firstName: 'Ada',
                lastName: 'Lovelace',
                email: 'ADA@EXAMPLE.COM',
                role: 'admin'
            };
    
            const formatted = formatUser(user);
    
            const rows = [
                { label: 'add(2, 3)',        value: add(2, 3) },
                { label: 'add("2", 3)',      value: add('2', 3) + '  ← string concat!' },
                { label: 'formatted.name',   value: formatted.name },
                { label: 'formatted.email',  value: formatted.email },
                { label: 'formatted.isAdmin', value: formatted.isAdmin },
                { label: 'typeof add',       value: typeof add }
            ];
    
            const out = document.getElementById('output');
            rows.forEach(function (row) {
                const div = document.createElement('div');
                div.className = 'row';
                div.innerHTML =
                    '<span class="label">' + row.label + '</span>' +
                    '<span class="value">' + row.value + '</span>';
                out.appendChild(div);
            });
        </script>
    
    </body>
    </html>

    Note the second row: add('2', 3) returns "23". That is the bug TypeScript would have caught. But at runtime — after compilation — the JavaScript engine has no idea the types were ever annotated. It sees the same function it always would have.

    The type system is a developer tool

    Think of TypeScript as a linter that understands your data. It checks your work while you write, then gets out of the way. It is not a runtime, not a framework, and not a different language at execution time.

    Full Comparison

    Here is every meaningful difference in one table.

    JavaScript vs TypeScript
    Aspect JavaScript TypeScript
    What it is The runtime language of the web JavaScript plus a static type system
    File extension .js .ts (.tsx for React)
    Runs in the browser? Yes, directly No — must be compiled to JavaScript first
    Build step required? No Yes — a compiler or bundler
    Typing Dynamic — checked at runtime, if at all Static — checked at compile time
    When errors appear At runtime, in front of users In the editor, before running
    Type annotations None possible Written inline; erased at compile time
    Runtime performance Baseline Identical — types are erased
    Bundle size impact Baseline Zero — nothing from the type system ships
    Editor autocomplete Limited — guesses from usage Precise — knows every property and type
    Refactoring safety Manual — easy to miss a call site The compiler finds every usage
    Learning curve Smaller — one language to learn Larger — JavaScript plus the type system
    Setup cost None Install, configure, build step
    Error reporting Runtime exceptions, console errors Compile errors with file, line, and reason
    Best for Scripts, prototypes, small sites, learning Applications, teams, long-lived codebases
    Maintained by TC39 / ECMAScript standard Microsoft, as an open-source project
    The two rows that decide it

    Look at “When errors appear” and “Refactoring safety”. Everything else is a trade-off you can live with either way — those two are the reason large teams adopt TypeScript.

    When to Use Which

    TypeScript is not automatically better. It has a real setup cost, and that cost is only worth paying when the project justifies it.

    Plain JavaScript

    Reach for JS when…

    The script is small — under a few hundred lines.

    You are prototyping or experimenting and want zero setup.

    It is a one-off script, a bookmarklet, or a quick demo.

    You are learning to program and want to focus on fundamentals.

    The project will not be maintained after it ships.

    TypeScript

    Reach for TS when…

    The codebase will outlive the people who wrote it.

    More than one developer works on it.

    It has a public API that others consume.

    Refactoring is frequent — the compiler catches every broken call site.

    You are already using a framework that expects it — React, Next.js, Angular, Vue.

    A practical rule of thumb

    • Under 500 lines, one developer, one use: plain JavaScript.
    • Over a few thousand lines, or a team: TypeScript.
    • A library or package others will import: TypeScript, and ship the type definitions.
    • A framework that ships with TS support: use TypeScript — you are already paying the setup cost.
    • A quick script to move some files around: plain JavaScript, obviously.
    TypeScript is not a silver bullet

    A badly typed codebase is worse than a plain JavaScript one, because it gives the illusion of safety. Annotating everything as any gives you all the verbosity of TypeScript and none of the protection. Typing well takes practice.

    Migrating from JavaScript to TypeScript

    TypeScript was designed for gradual adoption. You do not rewrite the project — you convert it one file at a time while it keeps working.

    The incremental path

    1 Install
    Add TypeScript to the project Install the compiler and create a tsconfig.json. Start with allowJs and checkJs turned on, and strict off.
    2 Rename
    Convert one file at a time Rename a single .js file to .ts. It will compile immediately — the types are all inferred. Fix any errors, then commit and move on.
    3 Annotate
    Add types to the important parts Start with function parameters, return types, and shared data shapes. Leave the rest inferred.
    4 Tighten
    Turn on strict mode Once most files are typed, set strict: true and fix the errors that appear. This is the step that catches the null and undefined bugs.

    What the migration looks like

    Step 1 — rename, no other changes
    // utils.ts — renamed from utils.js // Compiles immediately. Types // are inferred from usage. export function formatPrice(value) { return '$' + value.toFixed(2); } export function applyDiscount(price, rate) { return price * (1 - rate); }
    Step 2 — annotate the public API
    // utils.ts — parameters and returns typed export function formatPrice(value: number): string { return '$' + value.toFixed(2); } export function applyDiscount( price: number, rate: number ): number { return price * (1 - rate); }

    Configuring for gradual adoption

    {
        "compilerOptions": {
            "target": "ES2022",
            "module": "ESNext",
    
            // Allow .js files in the project
            "allowJs": true,
    
            // Report errors in .js files too (optional, stricter)
            "checkJs": false,
    
            // Do not fail the build on errors during migration
            "noEmitOnError": false,
    
            // Start loose, tighten later
            "strict": false,
    
            "outDir": "./dist",
            "rootDir": "./src"
        },
        "include": ["src/**/*"]
    }
    Convert the leaves first

    Start with files that nothing else imports — utility functions, constants, small helpers. Once those are typed, the files that import them get better type inference automatically, and the migration accelerates.

    You can stop halfway

    A project with some .ts files and some .js files is a perfectly valid state, and many projects stay that way forever. TypeScript does not demand completion.

    Common Misconceptions

    These come up constantly, and each one leads people to the wrong decision about TypeScript.

    • “TypeScript is a different language.” It is a superset. Every JavaScript program is a TypeScript program. You are not learning a new language — you are learning a type system on top of the one you already know.
    • “TypeScript replaces JavaScript.” It compiles to JavaScript. The browser runs the JavaScript. Nothing about the runtime changes.
    • “TypeScript is slower at runtime.” All the types are erased at compile time. The JavaScript that ships is byte-for-byte equivalent to what you would have written by hand.
    • “I need to rewrite my whole project.” You can rename one file at a time. TypeScript was explicitly designed for incremental adoption, and mixed projects are supported natively.
    • “Types catch all bugs.” They catch type errors. A function that adds when it should subtract compiles fine. Logic bugs are still logic bugs.
    • “Types slow down development.” Early on, writing types is extra work. After a few weeks, most developers report the opposite — autocomplete and refactoring save more time than the annotations cost.
    • “any is a fine escape hatch.” Occasional use is reasonable. Widespread any removes all the benefit while keeping all the syntax — you get JavaScript with extra steps.
    • “TypeScript is only for big companies.” A solo developer on a project that will exist for a year benefits just as much. The threshold is project lifetime and change frequency, not team size.
    The honest summary

    TypeScript costs you a build step and some annotation effort. In exchange you get fewer bugs in production, better tooling, and safer refactoring. Whether that trade is worth it depends entirely on the project.

    Best Practices

    If you are using TypeScript, these habits get the most out of it. If you are not, they are good reasons to consider it.

    ✅

    Turn on strict mode

    strict: true in tsconfig. It catches the most bugs, especially around null and undefined.

    🎯

    Annotate function boundaries

    Parameters and return types on exported functions. Everything inside can be inferred.

    🚫

    Avoid any

    Use unknown when you truly do not know. any turns off checking entirely.

    🔗

    Prefer unions to enums

    type Status = 'on' | 'off' produces simpler JavaScript than an enum and works everywhere.

    🏷️

    Name types clearly

    User, Product, OrderStatus — not IUser or T1.

    📦

    Keep types close to the code

    Define a type next to the function that uses it, unless it is shared across the project.

    ⚙️

    Run tsc in CI

    Fast transpilers skip type checking. Run tsc --noEmit separately to catch what they miss.

    📝

    Let inference work

    const name = 'Ada' is already a string. Do not annotate what the compiler already knows.

    🔄

    Migrate one file at a time

    There is no need to convert everything at once. The project keeps working throughout.

    The one-line summary

    Write plain JavaScript for small projects and learning. Add TypeScript when the codebase will live long enough for the type checking to pay for its setup cost.

    Frequently Asked Questions

    1. What is the main difference between JavaScript and TypeScript?

    TypeScript is JavaScript with a static type system layered on top. The types are checked while you write the code, then stripped out before it runs. Every valid JavaScript file is also valid TypeScript — TypeScript is a strict superset of JavaScript.

    2. Does TypeScript replace JavaScript?

    No. Browsers and Node.js run JavaScript, not TypeScript. A TypeScript compiler converts your .ts files into plain .js files, and those are what actually execute. TypeScript is a development-time tool, not a runtime.

    3. Is TypeScript a different programming language?

    It is best understood as a typed superset of JavaScript rather than an entirely separate language. Every JavaScript program is a TypeScript program. TypeScript adds syntax for types, and the compiler removes that syntax to produce JavaScript.

    4. Do I need to learn JavaScript before TypeScript?

    Yes. TypeScript is JavaScript plus types, so you need the JavaScript fundamentals first — variables, functions, arrays, objects, the DOM, and events. Trying to learn TypeScript without JavaScript is like learning to write in a formal style before you can write sentences.

    5. Can I use TypeScript in the browser directly?

    No, not directly. Browsers do not understand TypeScript. You either compile it to JavaScript ahead of time with the tsc compiler or a bundler, or in some development setups a tool such as esbuild transpiles it on the fly.

    6. Does TypeScript make a program faster?

    No. Types are erased at compile time, so the JavaScript that runs has the same performance as if you had written it by hand. TypeScript speeds up development — fewer bugs, better autocomplete, safer refactors — not execution.

    7. What does any mean in TypeScript?

    any disables type checking for that value. It lets you assign it to anything and call anything on it without errors. It is useful as an escape hatch during migration, but overusing it defeats the purpose of TypeScript — you end up with JavaScript plus extra syntax.

    8. What is the difference between interface and type in TypeScript?

    Both describe the shape of an object and are largely interchangeable. interface is preferred for object shapes because it can be extended and merged across declarations. type is more flexible — it can also describe unions, intersections, tuples, and primitive aliases.

    9. Should I use TypeScript for every project?

    No. Small scripts, quick prototypes, and one-off pages are often simpler in plain JavaScript. TypeScript earns its setup cost on projects with multiple developers, longer lifetimes, larger codebases, or shared APIs — anywhere a wrong type could cost real debugging time.

    10. How do I migrate an existing JavaScript project to TypeScript?

    Incrementally. Rename one file at a time to .ts, turn on allowJs and checkJs, start with strict set to false, and tighten the compiler options as the codebase gets typed. There is no need to rewrite everything at once — TypeScript is designed for gradual adoption.

    11. What is strict mode in TypeScript?

    strict is a compiler flag that turns on several stricter type checks at once, including noImplicitAny, strictNullChecks, and strictFunctionTypes. It catches more bugs, but requires more annotation. New projects should start with strict enabled.

    12. Does TypeScript have a runtime cost?

    None at all in production. Type annotations, interfaces, and type aliases are all erased by the compiler and never appear in the JavaScript that ships to the browser. The only cost is the compile step during development.

    Key Takeaways

    • TypeScript is JavaScript plus a static type system — a strict superset, not a replacement.
    • Types are checked while you write, then erased before the code runs.
    • Browsers and Node.js run JavaScript. TypeScript must be compiled first.
    • Type annotations leave no trace in the output, so there is zero runtime cost.
    • TypeScript catches typos, wrong argument types, missing arguments, null access, and wrong return types.
    • It does not catch logic errors — a function that adds instead of subtracting compiles fine.
    • The biggest practical benefit is editor autocomplete and safe refactoring.
    • Use plain JavaScript for scripts, prototypes, and learning.
    • Use TypeScript for applications, teams, libraries, and long-lived codebases.
    • Migration is incremental — rename one file at a time, keep the project working.
    • Turn on strict mode and avoid any.
    • Transpilers like esbuild skip type checking — run tsc --noEmit in CI.

    What to Learn Next

    If you are new to JavaScript entirely, start there. Read What Is JavaScript? for the fundamentals — variables, functions, arrays, objects, the DOM, and events.

    Once the basics are solid, the natural next steps are JavaScript Array Methods, JavaScript Functions Explained, and Working with the DOM. From there, move on to Async and Await and Fetching Data with the Fetch API.

    If you are ready for TypeScript, look for guides on the type system itself — interfaces, unions, generics, and tsconfig.json. And if you are still connecting the pieces, read HTML vs CSS and How Web Browsers Work for the surrounding context.

    Practice Challenge

    The best way to understand the difference is to write the same code twice and see what each language catches. This exercise takes about twenty minutes.

    1. Create app.js and app.ts in the same folder.
    2. In both files, write a function calculateTotal(price, quantity) that returns price * quantity, with no type annotations in either file.
    3. Add a line that calls calculateTotal('10', 3) and logs the result. Run the JavaScript version and note the output — it will be the string "101010".
    4. Now install TypeScript with npm install --save-dev typescript and run npx tsc --init to create a tsconfig.json. Set strict to true.
    5. Compile the TypeScript file with npx tsc app.ts. Read the error — it will point at the string argument.
    6. Fix the call to pass 10 instead of '10'. Compile again — it succeeds.
    7. Open the compiled app.js and compare it to your original. Confirm that the output contains no type annotations at all.
    8. Now add types to the function: function calculateTotal(price: number, quantity: number): number.
    9. Try calling it with a missing argument. Note the error message — it names the exact problem and the line.
    10. Create an interface Product { name: string; price: number; } and write a function that takes a Product. Try accessing a property that does not exist — note the error.
    11. Add a union type: type Status = 'in-stock' | 'out-of-stock', and write a function that accepts it. Try passing a string that is not one of the two values.
    12. Finally, compare the compiled output of your fully typed app.ts against the original app.js. Confirm they are functionally identical.

    If you complete those steps, you have seen the same bug happen silently in JavaScript and get caught immediately in TypeScript, watched the compiler strip every annotation from the output, and confirmed that the runtime behavior is unchanged. That is the whole trade: TypeScript does not change what your program does — it changes when you find out that it does the wrong thing.

    Inar Learn
    Inar Learnhttps://inarlearn.com
    Inar Learn is an innovative online learning platform offering high-quality courses, tutorials, and resources to help learners gain practical skills and grow their knowledge.

    Related Articles

    LEAVE A REPLY

    Please enter your comment!
    Please enter your name here