Best 100 PHP Exercises And Solutions
PHP Basic Exercises: 100+ Practice Problems with Solutions

Triple Equals in TypeScript: When to Use === vs == and Why It Still Matters

April 2, 2026

Last updated: April 4, 2026

Here is a fact that surprises many developers moving from JavaScript to TypeScript: the TypeScript compiler will sometimes catch a dangerous == comparison with a type error – but not always. And the times it stays quiet are exactly the times a bug can slip through to production. Understanding the TypeScript strict equality operator (===), when TypeScript’s type system offers genuine protection, and when it does not, is the difference between code that merely compiles and code that behaves correctly at runtime.

By the end of this article you will be able to explain why === still matters in TypeScript, identify the common traps that any types and union types create, and configure ESLint to enforce safe comparisons across your entire codebase.

How the TypeScript Compiler Handles == in Practice

The TypeScript compiler does catch many unsafe == comparisons – but only when the static types make the comparison obviously wrong.

Step 1 – Observe where the compiler helps you

Create a file equality-demo.ts:

const a: number = 42;
const b: string = 'hello';

if (a == b) {  // TypeScript error: This condition will always return 'false' since the types 'number' and 'string' have no overlap.
  console.log('equal');
}

Run tsc equality-demo.ts. You will see an error pointing directly at the comparison. The compiler recognises that a number and a string can never be == equal in a meaningful sense, so it flags it.

This is genuinely useful. TypeScript acts as a first line of defence against the most obvious coercion mistakes.

Step 2 – Observe where the compiler stays silent

Now replace the types with a union:

const a: string | number = 42;
const b: string | number = '42';

if (a == b) {  // No error - both types overlap
  console.log('equal');
}

Run tsc again. No error. Both variables could plausibly be the same type at runtime, so the compiler allows the comparison. But 42 == '42' is true in JavaScript – and almost certainly not what you intended.

Step 3 – Understand the any escape hatch

function checkValue(x: any, y: any) {
  if (x == y) {  // No error - 'any' disables type checking entirely
    return true;
  }
  return false;
}

checkValue(0, false); // returns true - coercion fires

Any value typed as any – which frequently arrives from external API responses, JSON.parse, or third-party libraries without type definitions – bypasses the compiler’s safety checks entirely.

Before / After comparison

// Before - vulnerable to coercion
function isActive(status: string | number) {
  return status == 1;  // '1' == 1 is true - probably not intended
}

// After - explicit and safe
function isActive(status: string | number) {
  return status === 1 || status === '1';  // clear about what you accept
}

The second version documents intent. It also makes it trivial to audit what the function actually accepts.

Closing: The Refined Answer

Back to the opening question – does strict equality still matter in TypeScript? Yes, for two reasons that operate at different layers.

At the compiler layer, TypeScript catches many == comparisons involving obviously incompatible types and reports them as errors. That is real, tangible protection.

At the runtime layer, TypeScript is not there. any types, union types, and values arriving from external inputs all bypass static analysis. The JavaScript the compiler emits is what actually runs – and JavaScript’s coercion rules apply in full.

The recommendation is straightforward: default to === throughout your TypeScript code, matching the established JavaScript best practice. When you genuinely need relaxed comparison – the == null idiom being the most defensible example – make it explicit with a comment. For everything else, let ESLint’s eqeqeq rule enforce consistency automatically so you never need to rely on memory alone.

If you are learning TypeScript as part of a broader move into typed, server-side development, you might also find it useful to explore Web Development with Python in 2026 – FastAPI, Django & Flask Guide for patterns in statically-typed ecosystems beyond JavaScript – or revisit the foundations with Mastering PHP for Beginners: Your First Steps into Web Development if you work across multiple backend languages.

If you are building a TypeScript project and would like professional guidance on code quality, tooling configuration, or architecture, get in touch with the team at drs-web.co.uk/contact – we are happy to help.

Stack Overflow logo  -  developer Q&A about using strict equality (===) in TypeScript
Stack Overflow logo – developer Q&A about using strict equality (===) in TypeScript

Image: Stack Overflow

Stack Overflow logo  -  developer Q&A about using strict equality (===) in TypeScript
Stack Overflow logo – developer Q&A about using strict equality (===) in TypeScript

Image: Stack Overflow

By the end of this guide you will know exactly when to use === instead of == in TypeScript, understand the one narrow exception where == is acceptable, and have a working ESLint rule that turns unsafe comparisons into a hard build error. The whole setup takes under ten minutes – and it will prevent an entire class of silent runtime bugs from ever reaching production.

Prerequisites

Before reading on, you should be comfortable with:

  • Basic JavaScript syntax and the concept of type coercion
  • What TypeScript is and how it compiles to JavaScript – if you are brand new to the language, Découvrez TypeScript – OpenClassrooms is an excellent starting point
  • Running tsc or working inside a TypeScript-aware editor such as VS Code

No advanced TypeScript knowledge is required. Familiarity with primitive types (string, number, boolean) is sufficient.

Step 1 – Understand Why == Is Still Dangerous in a Typed Language

TypeScript compiles to JavaScript. The equality operators you write go into the emitted JavaScript unchanged, and JavaScript’s coercion rules apply at runtime regardless of what your type annotations say.

To understand the problem from first principles, consider how == works. The Abstract Equality Comparison algorithm attempts to convert operands to a common type before comparing them. Think of it like a translator who, when asked to compare a French sentence with an English one, silently translates both into Latin first – and sometimes picks a translation you did not expect.

console.log(1 == '1');          // true  - number coerced to string
console.log(0 == false);        // true  - boolean coerced to number
console.log(null == undefined); // true  - special case in the spec
console.log('' == false);       // true  - both coerce to 0

Each of these returns false with ===, because strict equality checks both value and type with no conversion:

console.log(1 === '1');          // false
console.log(0 === false);        // false
console.log(null === undefined); // false
console.log('' === false);       // false

TypeScript’s designers kept both operators deliberately to maintain full compatibility with JavaScript. Removing == would have broken every existing JS codebase that TypeScript aims to embrace. That pragmatic decision means the coercion footgun is still available, even in a strictly-typed project.

Common mistake: Assuming that because TypeScript knows your variable is a number, comparing it with == is always safe. Whether the compiler complains depends on the static types involved – not on whether coercion could cause a problem at runtime.

Step 2 – Use === as Your Default for All Comparisons

The rule is simple: use === everywhere unless you have a specific, documented reason not to. Here is the before/after for the most common situation – comparing a value from an external source:

Before (unsafe):

const userInput: any = req.body.age; // could be '25' or 25

if (userInput == 25) {
  grantAccess(); // fires for both '25' and 25 - coercion silently bridges the gap
}

After (safe):

const userInput: any = req.body.age;

if (Number(userInput) === 25) {
  grantAccess(); // explicit conversion, then strict check - intent is clear
}

The Number() call makes the conversion visible to every reader. If it fails, Number('banana') returns NaN, and NaN === 25 is false – which is the correct, safe outcome.

TypeScript enums are another source of subtle coercion bugs. Enums compile to numeric or string values at runtime, and == will happily bridge the gap between an enum member and a raw boolean:

enum Status { Active = 1, Inactive = 0 }

const current = Status.Active;
console.log(current == true);  // true  - number 1 coerces to boolean true
console.log(current === true); // false - correct

Troubleshooting: If your TypeScript compiler reports This condition will always return 'false' since the types 'Status' and 'boolean' have no overlap, that is the compiler catching a type mismatch at compile time. It does not mean coercion cannot occur – it means the types are distinct enough for the compiler to flag it. With any or union types, no warning appears, and coercion still fires silently at runtime.

Step 3 – Recognise the One Accepted Exception: == null

JavaScript has a quirk that TypeScript developers sometimes exploit deliberately: null == undefined returns true. This means value == null is a compact shorthand for checking whether a value is either null or undefined simultaneously.

function printName(name: string | null | undefined) {
  if (name == null) {
    console.log('No name provided');
    // true for both null and undefined
    return;
  }
  console.log(name.toUpperCase());
}

printName(null);      // No name provided
printName(undefined); // No name provided
printName('alice');   // ALICE

The strict equivalent is equally readable and leaves no ambiguity about intent:

if (name === null || name === undefined) {
  console.log('No name provided');
}

Both approaches are valid. The == null form is shorter; the === null || === undefined form is explicit. Choose one style and apply it consistently across your project.

Common mistake: Using == null without a comment and then fielding a code-review question about whether it is a typo. If you use this pattern, add a brief inline note – // null or undefined – so reviewers understand it is intentional.

Troubleshooting: If ESLint reports Expected '===' and instead saw '==' on a value == null check, your ESLint config is not using the "null": "ignore" option. See Step 4 for the correct configuration.

Step 4 – Enforce === Across Your Codebase with ESLint

Relying on developer discipline alone does not scale. The eqeqeq ESLint rule converts any remaining unsafe == usage into a hard lint error, catching it during development rather than in production.

Add this to your .eslintrc.json:

{
  "rules": {
    "eqeqeq": ["error", "always", { "null": "ignore" }]
  }
}

The "null": "ignore" option permits the deliberate == null pattern from Step 3 while blocking all other == usage. Run the linter against your TypeScript files:

eslint --ext .ts src/

If you see output like:

src/auth.ts
  12:12  error  Expected '===' and instead saw '=='  eqeqeq

that is the rule working correctly. The file path and line number tell you exactly where to fix. Replace the == with === and, if needed, add an explicit type conversion before the comparison.

To make this a hard gate in CI, add the lint step to your pipeline before the build. A failed lint run blocks the merge, so unsafe comparisons never reach code review.

Common mistake: Adding eqeqeq as a "warn" rather than "error". Warnings are easy to ignore under time pressure. Set it to "error" from the start so the rule has teeth.

For projects using @typescript-eslint, consider pairing eqeqeq with @typescript-eslint/strict-boolean-expressions. This companion rule catches a related class of coercion bugs – cases where a non-boolean value such as a string or number is used directly in a conditional, relying on JavaScript’s truthy/falsy rules rather than an explicit comparison.

Next Steps

  • Add the eqeqeq ESLint rule to your project today – it takes under five minutes and immediately flags any existing unsafe comparisons
  • Enable TypeScript’s strict compiler flag, which reduces reliance on any and narrows the surface area where runtime coercion can occur
  • Explore branded types and the unknown type as safer alternatives to any for values from external sources such as APIs and form inputs
  • Review the @typescript-eslint/strict-boolean-expressions rule to catch related coercion issues in conditional statements

If you are working on a TypeScript project and want guidance on code quality, linting strategy, or developer tooling, get in touch at drs-web.co.uk/contact – we are happy to help.

Frequently Asked Questions

Q: Does TypeScript automatically prevent type coercion bugs from ==?
A: Only partially. TypeScript will flag comparisons between types with no overlap (e.g. number == string in strict mode), but stays silent when types overlap – such as union types – or when any is involved. Runtime coercion can still occur in those cases.

Q: Is there ever a good reason to use == in TypeScript?
A: The == null pattern – which returns true for both null and undefined – is the most commonly accepted exception. It should always be documented clearly so readers do not mistake it for an oversight.

Q: Will adding TypeScript to my JavaScript project make == comparisons safe?
A: No. TypeScript compiles to JavaScript and preserves your equality operators in the emitted code. The coercion rules that apply in JavaScript apply equally at runtime in TypeScript projects.

Q: How do I enforce === across my entire TypeScript codebase?
A: Add the ESLint rule "eqeqeq": ["error", "always"] to your .eslintrc.json and run ESLint as part of your CI pipeline. This turns unsafe == usage into a hard build error.

Q: Does this apply to frameworks like React or Angular built with TypeScript?
A: Yes. The equality operators behave identically regardless of the framework. The same === best practices and ESLint configuration apply to any TypeScript project.

Source: https://stackoverflow.com/questions/57125700/why-use-triple-equal-in-typescript

This article was researched and written with AI assistance, then reviewed for accuracy and quality. Kev Parker uses AI tools to help produce content faster while maintaining editorial standards.

Kev Parker

Kev Parker writes step-by-step web development tutorials that developers can run in their own labs; he focuses on deployable patterns and reproducible fixes for common production issues.

Need help with your web project?

From one-day launches to full-scale builds, DRS Web Development delivers modern, fast websites.

Get in touch

    Comments are closed.