TypeScript builds on JavaScript's runtime methods and adds its own compile-time utilities. Most developers know the basics — map, filter, reduce — but a lot of genuinely useful methods and utility types get overlooked. Here's a practical tour, from the familiar to the underused.
1. The array methods everyone "knows" (but half-knows)
Array.prototype.map, filter, reduce
These are the bread and butter of functional-style TypeScript. Quick refresher with types attached:
const numbers: number[] = [1, 2, 3, 4, 5];
const doubled: number[] = numbers.map((n) => n * 2);
const evens: number[] = numbers.filter((n) => n % 2 === 0);
const sum: number = numbers.reduce((acc, n) => acc + n, 0);
Array.prototype.find and findIndex
Returns the first matching element (or undefined), not an array — a common source of bugs when people confuse it with filter.
interface User {
id: number;
name: string;
}
const users: User[] = [
{ id: 1, name: "Asha" },
{ id: 2, name: "Ravi" },
];
const user = users.find((u) => u.id === 2); // User | undefined
2. The ones developers forget exist
Array.prototype.flatMap
Combines map and flat in one pass — great for when a mapping function returns an array per item.
const sentences: string[] = ["hello world", "typescript rocks"];
const words: string[] = sentences.flatMap((s) => s.split(" "));
// ["hello", "world", "typescript", "rocks"]
Array.prototype.at
Lets you index from the end without length - 1 gymnastics.
const list = [10, 20, 30, 40];
const last = list.at(-1); // 40
Object.entries, Object.fromEntries
Useful for transforming objects the same way you'd transform arrays.
const prices: Record<string, number> = { apple: 1, banana: 2 };
const doubledPrices = Object.fromEntries(
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
// { apple: 2, banana: 4 }
Array.prototype.some and every
Both return booleans — some checks "at least one," every checks "all." Cleaner than manual loops for validation logic.
const scores = [88, 92, 79, 95];
const allPassed = scores.every((s) => s >= 60); // true
const anyFailed = scores.some((s) => s < 60); // false
3. TypeScript-specific utility types (not runtime methods, but just as valuable)
These aren't methods you call — they're compile-time helpers that reshape types. Underused because people don't think to reach for them.
Partial<T> and Required<T>
interface Settings {
theme: string;
language: string;
}
function updateSettings(update: Partial<Settings>) {
// caller can pass just { theme: "dark" }
}
Pick<T, K> and Omit<T, K>
interface Product {
id: number;
name: string;
price: number;
description: string;
}
type ProductSummary = Pick<Product, "id" | "name">;
type ProductWithoutDescription = Omit<Product, "description">;
Record<K, V>
Great for typing dictionaries/maps cleanly instead of { [key: string]: V }.
type StatusMap = Record<"success" | "error" | "loading", string>;
const messages: StatusMap = {
success: "Done!",
error: "Something went wrong.",
loading: "Please wait...",
};
ReturnType<T> and Parameters<T>
Handy when you want to derive types from a function instead of duplicating them.
function createUser(name: string, age: number) {
return { name, age, id: crypto.randomUUID() };
}
type NewUser = ReturnType<typeof createUser>;
type CreateUserArgs = Parameters<typeof createUser>;
4. String methods that quietly save time
String.prototype.padStart / padEnd
const invoiceId = "42".padStart(6, "0"); // "000042"
String.prototype.replaceAll
No more regex-with-global-flag just to replace every occurrence.
const csv = "a,b,c".replaceAll(",", " | "); // "a | b | c"
5. A note on optional chaining and nullish coalescing
Not "methods" in the traditional sense, but they belong here because they replace patterns that used to require verbose helper functions.
interface Config {
server?: {
port?: number;
};
}
const config: Config = {};
const port = config.server?.port ?? 3000; // 3000, no runtime errors
Wrapping up
Most TypeScript codebases lean on map/filter/reduce and stop there — which works, but leaves a lot of expressiveness on the table. Methods like flatMap, at, and Object.fromEntries, paired with utility types like Pick, Omit, and ReturnType, often let you delete a helper function or a manual type declaration entirely.
The best way to internalize these is to keep the TypeScript Utility Types docs and MDN's Array reference open while refactoring — you'll start spotting places to swap in a cleaner method almost every time.
Top comments (0)