At Least One Key
typescripthelper-typestypedefinition
type AtLeastOne<T> = {
[K in keyof T]: Pick<T, K> & Partial<Omit<T, K>>;
}[keyof T];
// Usage:
type A = {
id?: string;
name?: string;
isActive?: boolean;
};
type AtLeastOneA = AtLeastOne<A>;
// Requires at least one of 'id', 'name', or 'isActive' to be defined
...
Deep Partial Type
typescripthelper-typestypedefinitionoptional
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
// Usage:
type A = {
name: string;
details: {
age: number;
address: { city: string; zip: string };
};
};
type PartialA = DeepPartial<A>;
/*
Type PartialA:
{
name?: string;
details?: {
age?: number;
address?: { city?: string; zip?: string };
};
}
*/
...
Deep Readonly Type
typescripthelper-typestypedefinitionreadonly
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
// Usage:
type A = {
name: string;
details: {
age: number;
address: { city: string; zip: string };
};
};
type ReadonlyA = DeepReadonly<A>;
/*
Type ReadonlyA:
{
readonly name: string;
readonly details: {
readonly age: number;
readonly address: { readonly city: string; readonly zip: string };
};
}
*/
...
Deep Required Type
typescripthelper-typestypedefinitionrequired
type DeepRequired<T> = T extends object
? { [K in keyof T]-?: DeepRequired<T[K]> }
: T;
// Usage:
type A = {
id?: string;
name?: string;
details?: {
age?: number;
address?: { city?: string; zip?: string };
};
};
type RequiredA = DeepRequired<A>;
// Result: { id: string; name: string; details: { age: number; address: { city: string; zip: string }; }; }
...
Exclusive Types
typescripthelper-typestypedefinition
type Exclusive<T, U = T> = T | U extends Record<string, unknown>
?
| ({ [P in Exclude<keyof T, keyof U>]?: never } & U)
| ({ [P in Exclude<keyof U, keyof T>]?: never } & T)
: T | U;
// Usage:
type A = { name: string; email?: string; provider?: string };
type B = { name: string; phone?: string; country?: string };
type EitherOr = Exclusive<A, B>;
const w: EitherOr = { name: "John", email: "j@d.c" }; // ✅
const x: EitherOr = { name: "John", phone: "+123 456" }; // ✅
const y: EitherOr = { name: "John", email: "", phone: "" }; // ⛔️
const z: EitherOr = { name: "John", phne: "", provider: "" }; // ⛔️
...
Keys of Type
typescripthelper-typestypedefinition
type KeysOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
// Usage:
type A = { name: string; age: number; isActive: boolean, isDeleted: boolean };
type StringKeys = KeysOfType<A, string>; // "name"
type BooleanKeys = KeysOfType<A, boolean>; // "isActive" | "isDeleted"
...
Keys to Optional
typescripthelper-typestypedefinitionoptional
type OptionalKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// Usage:
type A = {
id: string;
name: string;
age: number;
};
type WithOptionalName = OptionalKeys<A, "name">;
// { id: string; age: number; name?: string }
type WithOptionalNameAndAge = OptionalKeys<A, "name" | "age">;
// Result: { id: string; name?: string; age?: number }
...
Nullable Keys
typescripthelper-typestypedefinitionnullable
type NullableKeys<T> = {
[K in keyof T]: null extends T[K] ? K : undefined extends T[K] ? K : never;
}[keyof T];
// Usage:
type A = {
id: string;
name?: string;
description: string | null;
};
type Nullable = NullableKeys<A>; // "name" | "description"
...
Omit Keys of Type
typescripthelper-typestypedefinitionomitkeys
type OmitKeysOfType<T, U> = {
[K in keyof T as T[K] extends U ? never : K]: T[K];
};
// Usage:
type A = {
id: string;
isActive: boolean;
data: number[];
};
type WithoutBoolean = OmitKeysOfType<A, boolean>; // { id: string; data: number[] }
...
Required Keys
typescripthelper-typestypedefinitionrequired
type RequiredKeys<T> = {
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
}[keyof T];
// Usage:
type A = {
id: string;
name?: string;
isActive: boolean;
};
type ReqKeys = RequiredKeys<A>; // "id" | "isActive"
...
Union to Intersection
typescripthelper-typestypedefinitionintersectionunion
type UnionToIntersection<U> = (U extends any ? (arg: U) => void : never) extends (arg: infer I) => void
? I
: never;
// Usage:
type A = { id: string };
type B = { name: string };
type C = { age: number };
type Intersected = UnionToIntersection<A | B | C>;
// { id: string } & { name: string } & { age: number }
...