Skip to main content

TypeScript Tips

Practical TypeScript techniques that make our codebase safer and more maintainable.

Prefer unknown Over any

When you don't know the type, use unknown instead of any. It forces you to narrow the type before using it:

function processInput(input: unknown) {
if (typeof input === "string") {
return input.toUpperCase();
}
if (typeof input === "number") {
return input * 2;
}
throw new Error("Unexpected input type");
}

Use Template Literal Types

Create precise string types:

type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIRoute = `/api/${string}`;
type EventName = `on${Capitalize<string>}`;

Utility Types You Should Know

// Make all properties optional
type PartialUser = Partial<User>;

// Make all properties required
type RequiredConfig = Required<Config>;

// Pick specific properties
type UserPreview = Pick<User, "id" | "name" | "avatar">;

// Exclude specific properties
type PublicUser = Omit<User, "password" | "email">;

// Create a record type
type UserMap = Record<string, User>;

Exhaustive Checks with never

Ensure all cases in a union are handled:

type Status = "active" | "inactive" | "pending";

function getStatusColor(status: Status): string {
switch (status) {
case "active": return "green";
case "inactive": return "gray";
case "pending": return "yellow";
default: {
const _exhaustive: never = status;
return _exhaustive;
}
}
}

Adding a new status to the union will cause a compile error until you handle it.