import { IsEmptyArray } from "./array"; import { If } from "./if"; import { Not } from "./not"; import { Pop } from "./pop"; /** * Returns boolean whether the first argument extends the second argument * @example * ```ts * // true * type Case1 = Extends<1, number> * // false * type Case2 = Extends * ``` */ export type Extends = [T] extends [Base] ? true : false; /** * Returns boolean whether the first argument doesn't extend the second argument * @example * ```ts * // false * type Case1 = Extends<1, number> * // true * type Case2 = Extends * ``` */ export type NotExtends = Not>; /** * Returns the third argument if the first argument extends the second argument (defaults to `true`), otherwise returns the fourth argument (defaults to `false`) * @example * ```ts * // 'valid' * type Case1 = IfExtends<1, number, 'valid'> * // 'invalid' * type Case2 = IfExtends<1, string, 'valid', 'invalid'> * ``` */ export type IfExtends = If< Extends, IfTrue, IfFalse >; /** * Returns the third argument if the first argument doesn't extend the second argument (defaults to `true`), otherwise returns the fourth argument (defaults to `false`) * @example * ```ts * // 'valid' * type Case1 = IfExtends<1, string, 'valid'> * // 'invalid' * type Case2 = IfExtends<1, number, 'valid', 'invalid'> * ``` */ export type IfNotExtends = If< NotExtends, IfTrue, IfFalse >; /** * Returns boolean whether the every element of first array argument extend the second argument * @example * ```ts * // true * type Case1 = ExtendsArr<[1, 2, 3], number> * // false * type Case1 = ExtendsArr<[1, '2', 3], number> * ``` */ export type ExtendsArr< T extends readonly unknown[], Base > = IsEmptyArray extends true ? true : Pop< T, { includeRemoved: true; } > extends readonly [infer Rest extends readonly unknown[], infer Removed] ? Extends extends true ? ExtendsArr : false : false;