UNPKG

ts-gems

Version:

Valuable typing extensions for TypeScript

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