Skip to main content

LinkedIn Posts

1. unknown > any

Visual

any vs unknown

Post Copy

The most dangerous TypeScript feature is also the easiest one to reach for.

any feels fast in the moment, but it quietly removes the exact protection TypeScript was supposed to give you.

I think unknown is one of the most underrated types in the language.

It still lets you accept uncertain data.

It just forces you to prove what that data is before you use it.

let data: unknown = "Hello TypeScript";

if (typeof data === "string") {
console.log(data.toUpperCase());
}
  • any = trust me
  • unknown = prove it

That one habit changes where bugs get caught.

#TypeScript #JavaScript #WebDevelopment #Programming #Frontend

2. never catches missing logic

Visual

missing case vs never

Post Copy

never looks pointless until it catches the bug you forgot to think about.

Most people treat it like a weird TypeScript edge case.

It is actually one of the cleanest ways to make sure a union is handled completely.

The real risk is not adding a new union member.

The real risk is forgetting every place that now needs to handle it.

type Shape = "circle" | "square";

function getArea(shape: Shape) {
switch (shape) {
case "circle":
return "Circle Area";
case "square":
return "Square Area";
default:
const neverValue: never = shape;
return neverValue;
}
}
  • missing case = silent risk
  • never = this path should be impossible

That is a very useful compiler error to have.

#TypeScript #JavaScript #Programming #CleanCode #SoftwareEngineering

3. Type predicates teach TypeScript

Visual

boolean vs type predicate

Post Copy

A normal boolean check runs your code.

A type predicate does something more valuable.

It tells TypeScript what became true after the check passed.

That matters a lot when you are working with API responses, form values, or anything that starts as unknown.

This is one of those features that feels advanced at first, but becomes very practical once it clicks.

type User = {
name: string;
email: string;
};

function isUser(value: unknown): value is User {
return (
typeof value === "object" &&
value !== null &&
"name" in value &&
"email" in value
);
}
  • boolean = true or false
  • type predicate = what is safe now

That is when narrowing starts feeling powerful instead of academic.

#TypeScript #JavaScript #APIs #Programming #WebDevelopment

4. satisfies is cleaner than as

Visual

as vs satisfies

Post Copy

I still see a lot of TypeScript code reaching for as by default.

That works, but it often tells the compiler to back off too early.

satisfies is usually the cleaner move for config objects and static mappings.

It checks the shape you need without throwing away useful inference.

That is a much better tradeoff in real code.

type Config = {
apiUrl: string;
timeout: number;
};

const config = {
apiUrl: "https://api.example.com",
timeout: 5000,
} satisfies Config;
  • as = trust me
  • satisfies = check me

The difference is small in syntax and big in safety.

#TypeScript #Frontend #DX #Programming #DeveloperTips

5. Hover the type before fixing the error

Visual

guess vs hover type

Post Copy

Most TypeScript debugging gets easier when you stop staring at the error and start inspecting the type.

My first move now is simple: hover the value.

That immediately shows what TypeScript currently knows, which is usually the real reason the error exists.

A lot of TS bugs are not deep.

They are just places where narrowing never happened.

function printPrice(price: string | number) {
return price.toFixed(2);
}
  • check the current type
  • compare it with the expected type
  • trace where the value came from

That workflow is faster than guessing.

#TypeScript #Debugging #JavaScript #LearnToCode #Developer

6. @ts-ignore is not a fix

Visual

ts-ignore vs real fix

Post Copy

@ts-ignore fixes the red line, not the underlying problem.

I am not saying it should never exist.

Sometimes it is useful during migrations or around awkward library edges.

But when it becomes the default response, TypeScript stops acting like a safety net and starts becoming decoration.

That is usually the wrong habit.

// @ts-ignore
someValue.doSomething();
  • @ts-ignore buys silence
  • a real fix buys confidence

The compiler is more useful when you let it argue with you.

#TypeScript #CodeReview #CleanCode #Programming #SoftwareDevelopment

7. Overloads make APIs feel smarter

Visual

union vs overloads

Post Copy

Function overloads are one of those TypeScript features that feel optional until you care about API quality.

A wide union signature can work perfectly and still feel vague to use.

Overloads make valid call patterns explicit.

That means better autocomplete, clearer intent, and fewer weird usages slipping through.

Good APIs do not just work.

They guide.

function format(value: string): string;
function format(value: number): string;

function format(value: string | number): string {
if (typeof value === "number") {
return value.toFixed(2);
}

return value.toUpperCase();
}
  • wide signature = flexible but blurry
  • overloads = explicit and easier to use

That is a developer experience decision, not just a type decision.

#TypeScript #APIDesign #DX #Programming #JavaScript

8. keyof stops fake property access

Visual

string key vs keyof

Post Copy

keyof is one of the smallest TypeScript features with one of the biggest long-term payoffs.

At first it just looks like syntax for generic helpers.

But what it really does is stop you from pretending every string is a valid property name.

That is a quiet source of bugs in reusable utilities.

Once keyof clicks, a lot of generic code starts making more sense.

function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
  • string can lie
  • keyof keeps keys honest

That is a very good trade.

#TypeScript #Generics #JavaScript #Coding #WebDev

9. import type is a clean habit

Visual

import vs import type

Post Copy

import type is one of those tiny habits that makes a codebase feel more intentional.

The benefit is not drama.

It is clarity.

When I read import type, I instantly know that symbol exists only for typing and not for runtime behavior.

That makes large files easier to scan and reason about.

import type { User } from "./types";
  • normal import = maybe runtime, maybe type
  • import type = intent is obvious

Small clarity compounds faster than most people think.

#TypeScript #Frontend #CodeQuality #JavaScript #Engineering

10. TypeScript matters most at boundaries

Visual

trust input vs validate input

Post Copy

The biggest TypeScript wins do not happen inside perfect internal code.

They happen at the edges, where data is uncertain and assumptions get expensive.

API responses, form input, localStorage, URL params.

That is where unknown, narrowing, predicates, and validation patterns start paying for themselves.

TypeScript is strongest when it protects you from trust you have not earned yet.

function handleResponse(data: unknown) {
if (isUser(data)) {
console.log(data.email);
}
}
  • trusted input creates bugs
  • validated input creates confidence

Type safety matters most where certainty is lowest.

#TypeScript #SoftwareEngineering #APIs #FrontendDevelopment #Programming