Designs complex generic types, refactors `any` types to strict alternatives, creates type guards and utility types, and resolves TypeScript compiler errors. Use when the user asks about TypeScript (TS) types, generics, type inference, type guards, removing `any` types, strict typing, type errors, `infer`, `extends`, conditional types, mapped types, template literal types, branded/opaque types, or utility types like `Partial`, `Record`, `ReturnType`, and `Awaited`.
97
97%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
TypeScript provides built-in utility types that transform types in common ways. Mastering these utilities is essential for advanced TypeScript programming.
Extracts the parameter types of a function type as a tuple:
function fetchUser(id: string, opts?: { timeout?: number }): Promise<User> {
// ...
}
type FetchUserParams = Parameters<typeof fetchUser>;
// Type: [id: string, opts?: { timeout?: number } | undefined]
// Use in wrapper functions
const fetchUserWithLogging = async (
...args: Parameters<typeof fetchUser>
): Promise<User> => {
console.log("Fetching user:", args[0]);
return fetchUser(...args);
};Extracts the return type of a function type:
function createUser(name: string, email: string) {
return {
id: crypto.randomUUID(),
name,
email,
createdAt: new Date(),
};
}
type User = ReturnType<typeof createUser>;
// Type: { id: string; name: string; email: string; createdAt: Date }Unwraps the type inside a Promise (including nested Promises):
type PromiseString = Promise<string>;
type NestedPromise = Promise<Promise<number>>;
type Unwrapped1 = Awaited<PromiseString>; // string
type Unwrapped2 = Awaited<NestedPromise>; // number
// Combine with ReturnType for async functions
async function fetchUser(id: string): Promise<User> {
// ...
}
type FetchUserResult = Awaited<ReturnType<typeof fetchUser>>;
// Type: User (not Promise<User>)When extending functions from external libraries that don't export their types:
import { fetchUser } from "external-lib";
// Extract and extend the return type
type FetchUserReturn = Awaited<ReturnType<typeof fetchUser>>;
export const fetchUserWithFullName = async (
...args: Parameters<typeof fetchUser>
): Promise<FetchUserReturn & { fullName: string }> => {
const user = await fetchUser(...args);
return {
...user,
fullName: `${user.firstName} ${user.lastName}`,
};
};Creates an object type with specified keys and value type:
type Role = "admin" | "user" | "guest";
type Permissions = Record<Role, string[]>;
const rolePermissions: Permissions = {
admin: ["read", "write", "delete"],
user: ["read", "write"],
guest: ["read"],
};
// Dynamic keys with constraint
function createLookup<K extends string, V>(
keys: K[],
getValue: (key: K) => V
): Record<K, V> {
const result = {} as Record<K, V>;
for (const key of keys) {
result[key] = getValue(key);
}
return result;
}Makes all properties optional:
interface User {
id: string;
name: string;
email: string;
}
type UpdateUserInput = Partial<User>;
// Type: { id?: string; name?: string; email?: string }
function updateUser(id: string, updates: Partial<User>): User {
// ...
}
updateUser("123", { name: "New Name" }); // OK - only updating nameMakes all properties required (opposite of Partial):
interface Config {
host?: string;
port?: number;
debug?: boolean;
}
type RequiredConfig = Required<Config>;
// Type: { host: string; port: number; debug: boolean }Creates a type by omitting specified properties:
interface User {
id: string;
name: string;
email: string;
password: string;
}
type PublicUser = Omit<User, "password">;
// Type: { id: string; name: string; email: string }
type CreateUserInput = Omit<User, "id">;
// Type: { name: string; email: string; password: string }Creates a type by picking specified properties (opposite of Omit):
interface User {
id: string;
name: string;
email: string;
password: string;
createdAt: Date;
}
type UserCredentials = Pick<User, "email" | "password">;
// Type: { email: string; password: string }Work with union types:
type AllColors = "red" | "green" | "blue" | "yellow";
type PrimaryColors = Extract<AllColors, "red" | "blue">;
// Type: "red" | "blue"
type NonPrimaryColors = Exclude<AllColors, "red" | "blue">;
// Type: "green" | "yellow"Removes null and undefined from a type:
type MaybeString = string | null | undefined;
type DefiniteString = NonNullable<MaybeString>;
// Type: stringCombine utilities to create reusable type helpers:
// A type that wraps any async function, extending its return type
type WrapFunction<
TFunc extends (...args: any) => any,
TAdditional = {}
> = (
...args: Parameters<TFunc>
) => Promise<Awaited<ReturnType<TFunc>> & TAdditional>;
// Usage
import { fetchUser, fetchPost } from "external-lib";
const fetchUserWithMeta: WrapFunction<
typeof fetchUser,
{ meta: { fetchedAt: Date } }
> = async (...args) => {
const user = await fetchUser(...args);
return {
...user,
meta: { fetchedAt: new Date() },
};
};| Utility | Use Case |
|---|---|
Parameters<T> | Wrapping functions, creating function variants |
ReturnType<T> | Extracting return types when not explicitly exported |
Awaited<T> | Unwrapping Promise types |
Record<K, V> | Creating object types with dynamic keys |
Partial<T> | Update/patch operations |
Required<T> | Ensuring all config options are provided |
Omit<T, K> | Removing sensitive or internal fields |
Pick<T, K> | Creating focused subsets of types |
Exclude<T, U> | Filtering union types |
Extract<T, U> | Selecting from union types |
NonNullable<T> | Removing null/undefined after validation |
async function getData(): Promise<string[]> {
return ["data"];
}
// This gives Promise<string[]>, not string[]
type Wrong = ReturnType<typeof getData>; // Promise<string[]>
// Use Awaited to unwrap
type Right = Awaited<ReturnType<typeof getData>>; // string[]function myFunc(x: number): string {
return String(x);
}
// Wrong - myFunc is a value, not a type
type Params = Parameters<myFunc>; // Error
// Correct - use typeof
type Params = Parameters<typeof myFunc>; // [x: number]