72 lines
1.4 KiB
TypeScript

/**
* Toolkit - Type Helpers
*
* TypeScript utility types and helper functions.
*/
/**
* Make specific properties optional
*/
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
/**
* Make specific properties required
*/
export type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
/**
* Deep partial (makes all nested properties optional)
*/
export type DeepPartial<T> = T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
/**
* Extract keys of a certain type
*/
export type KeysOfType<T, U> = {
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
/**
* Ensure all keys of a type are present
*/
export function ensureKeys<T extends Record<string, unknown>>(
obj: Partial<T>,
keys: (keyof T)[]
): obj is T {
return keys.every(key => key in obj);
}
/**
* Pick properties by value type
*/
export type PickByValue<T, V> = Pick<
T,
{
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T]
>;
/**
* Safely access nested property
*/
export function getNestedProperty<T>(
obj: unknown,
path: string,
defaultValue?: T
): T | undefined {
const keys = path.split(".");
let current: any = obj;
for (const key of keys) {
if (current === null || current === undefined || typeof current !== "object") {
return defaultValue;
}
current = current[key];
}
return current ?? defaultValue;
}