/**
 * 类型工具函数库
 * 提供对 TypeScript 类型的常见操作工具。
 */

// --------------------------- 类型工具 ---------------------------

/**
 * 从某个对象类型中挑选出指定的键。
 */
export type PickKeys<T, K extends keyof T> = {
    [P in K]: T[P];
};

/**
 * 从某个对象类型中排除指定的键。
 */
export type OmitKeys<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

/**
 * 将某些字段设置为可选。
 */
export type PartialByKeys<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

/**
 * 将某些字段设置为必填。
 */
export type RequiredByKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;

/**
 * 可为空的类型。
 */
export type Nullable<T> = T | null;

/**
 * 可为 undefined 的类型。
 */
export type Optional<T> = T | undefined;

/**
 * 确保某个变量类型的检查 (主要用于类型推断辅助)。
 */
export const assertType = <T>(value: T): T => value;

/**
 * 获取数组元素的类型。
 */
export type ArrayElement<A> = A extends readonly (infer T)[] ? T : never;

/**
 * 获取某个对象中字段的值组成的联合类型。
 */
export type ValueOf<T> = T[keyof T];

/**
 * 深部分可选：将嵌套对象所有字段设置为可选。
 */
export type DeepPartial<T> = {
    [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};

/**
 * 深部分必填：将嵌套对象所有字段设置为必填。
 */
export type DeepRequired<T> = {
    [K in keyof T]-?: T[K] extends object ? DeepRequired<T[K]> : T[K];
};

// --------------------------- 工具函数 ---------------------------

/**
 * 检查一个值是否为空 (null 或 undefined)
 * @param val 要检查的值
 */
export const isNullOrUndefined = (val: unknown): val is null | undefined => {
    return val === null || val === undefined;
};

/**
 * 检查一个值是否为对象。
 * @param val 要检查的值
 */
export const isObject = (val: unknown): val is Record<string, unknown> => {
    return typeof val === 'object' && val !== null && !Array.isArray(val);
};

/**
 * 检查一个对象是否为空 (没有属性)。
 * @param obj 要检查的对象
 */
export const isEmptyObject = (obj: Record<string, unknown>): boolean => {
    return Object.keys(obj).length === 0;
};
export type NonVoid<T> = T extends void ? never : T;