import { Primitive, Type } from './types.js'; type NonObj = Primitive | Function; /** * Returns Y if typeof T is "any", N otherwise */ export type IfAny = 0 extends 1 & T ? Y : N; /** * Returns "Y" if "T" is "never", "N" otherwise */ export type IfNever = [T] extends [never] ? Y : N; /** * Returns Y if T is undefined, N otherwise */ export type IfUndefined = IfEquals; /** * Returns "Y" if "T" is "never", "N" otherwise */ export type IfSymbol = IfEquals; /** * Returns Y if typeof T is "unknown", N otherwise */ export type IfUnknown = IfEquals; /** * Returns Y if typeof T is null, N otherwise */ export type IfNull = IfEquals; /** * Returns Y if typeof T is null, N otherwise */ export type IfNullish = IfNever extends true ? N : T extends null ? Y : T extends undefined ? Y : N; /** * Returns Y if typeof T is a tuple, N otherwise */ export type IfTuple = IfAny extends true ? N : IfNever extends true ? N : T extends readonly unknown[] ? number extends T['length'] ? N : Y : N; export type IfTupleOrAny = IfAny extends true ? Y : IfTuple; /** * Returns Y if typeof T is "Primitive", N otherwise */ export type IfPrimitive = IfNever extends true ? N : IfNull extends true ? Y : IfUndefined extends true ? Y : IfClass extends true ? N : IfFunction extends true ? N : T extends Primitive ? Y : N; export type IfPrimitiveOrAny = IfAny extends true ? Y : IfPrimitive; /** * Returns Y if typeof T is an empty object, N otherwise */ export type IfEmptyObject = IfEquals; /** * Returns Y if typeof T is an object, N otherwise */ export type IfObject = IfNever extends true ? N : T extends object ? T extends NonObj | any[] ? N : Y : N; export type IfObjectOrAny = IfAny extends true ? Y : IfObject; /** * Returns Y if typeof T is an empty object, N otherwise */ export type IfFunction = IfNever extends true ? N : T extends Type ? N : T extends Function ? Y : N; export type IfFunctionOrAny = IfAny extends true ? Y : IfFunction; /** * Returns Y if typeof T is a constructor type, N otherwise */ export type IfClass = IfNever extends true ? N : IfUndefined extends true ? N : T extends Type ? Y : N; export type IfClassOrAny = IfAny extends true ? Y : IfClass; /** * Returns "Y" if "T1" is exactly same with "T2", "N" otherwise */ export type IfEquals = IfObject | IfObject extends true ? (() => G extends EqualsWrapped ? 1 : 2) extends < G, >() => G extends EqualsWrapped ? 1 : 2 ? Y : N : (() => G extends T1 ? 1 : 2) extends () => G extends T2 ? 1 : 2 ? Y : N; type EqualsWrapped = T extends infer R & {} ? { [P in keyof R]: R[P] } : never; /** * Returns "Y" if type "T" matches "U", "N" otherwise */ export type IfCompatible = IfUndefined extends true ? IfEquals : IfUndefined extends true ? N : IfNever extends true ? IfEquals : IfNever extends true ? N : IfNull extends true ? IfEquals : IfNull extends true ? N : IfUnknown extends true ? Y : IfUnknown extends true ? Y : IfAny extends true ? Y : IfAny extends true ? Y : IfEmptyObject extends true ? IfObject : IfEmptyObject extends true ? IfObject : IfFunction extends true ? IfCompatibleFunction : IfObject extends true ? [T1] extends [T2] ? Y : N : [T1] extends [T2] ? Y : IfPrimitive extends true ? [T2] extends [T1] ? Y : N : N; type IfCompatibleFunction = IfFunction extends false ? N : IfFunction extends false ? N : T1 extends T2 ? Y : N;