diff --git a/index.d.ts b/index.d.ts index b00eea7da..f39c81ac6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -158,6 +158,9 @@ export type {IsUppercase} from './source/is-uppercase.d.ts'; export type {IsOptional} from './source/is-optional.d.ts'; export type {IsNullable} from './source/is-nullable.d.ts'; export type {TupleOf} from './source/tuple-of.d.ts'; +export type {IndexOf} from './source/index-of.d.ts'; +export type {LastIndexOf} from './source/last-index-of.d.ts'; +export type {IndicesOf} from './source/indices-of.d.ts'; // Template literal types export type {CamelCase, CamelCaseOptions} from './source/camel-case.d.ts'; diff --git a/source/index-of.d.ts b/source/index-of.d.ts new file mode 100644 index 000000000..5cf791389 --- /dev/null +++ b/source/index-of.d.ts @@ -0,0 +1,64 @@ +import type {GreaterThanOrEqual} from './greater-than-or-equal.d.ts'; +import type {ApplyDefaultOptions} from './internal/object.d.ts'; +import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts'; +import type {ReverseSign} from './internal/numeric.d.ts'; +import type {UnknownArray} from './unknown-array.d.ts'; +import type {IsAnyOrNever} from './internal/type.d.ts'; +import type {LiteralUnion} from './literal-union.d.ts'; +import type {IsEqual} from './is-equal.d.ts'; + +/* eslint-disable type-fest/require-exported-types */ +export type Inc = [...T, 1]; +export type Neg = ReverseSign; +export type IndexOfOptions = { + ignoreOptionalModifier?: boolean; + fromIndex?: number; +}; +/* eslint-enable type-fest/require-exported-types */ + +type DefaultIndexOfOptions = { + ignoreOptionalModifier: false; + fromIndex: 0; +}; + +export type IndexOf< + Array_ extends UnknownArray, Item, + Options extends IndexOfOptions = {}, +> = IsAnyOrNever extends true ? Array_ + : _IndexOf + >; + +type _IndexOf< + Array_ extends UnknownArray, Item, + Options extends Required, + F_Index extends number[] = [], + B_Index extends number[] = [1], + T_Index extends number[] = never, +> = + keyof Array_ & `${number}` extends never + // Backward search + ? Array_ extends readonly [...infer Rest, infer Last] + ? IsEqual extends true + ? _IndexOf, B_Index> + : _IndexOf, T_Index> + : Array_ extends readonly [] ? Neg + : IsEqual extends false ? Neg + : LiteralUnion + // Forward search + : Array_ extends readonly [(infer First)?, ...infer Rest] + ? GreaterThanOrEqual extends true + ? IsEqual extends true ? F_Index['length'] | ( + Options['ignoreOptionalModifier'] extends true ? never + : IsOptionalKeyOf extends false ? never + : _IndexOf>) + : _IndexOf> + : _IndexOf> + + : never; + +export {}; diff --git a/source/indices-of.d.ts b/source/indices-of.d.ts new file mode 100644 index 000000000..49610f901 --- /dev/null +++ b/source/indices-of.d.ts @@ -0,0 +1,66 @@ +import type {ApplyDefaultOptions} from './internal/object.d.ts'; +import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts'; +import type {UnknownArray} from './unknown-array.d.ts'; +import type {IsAnyOrNever} from './internal/type.d.ts'; +import type {Inc, Neg} from './index-of.d.ts'; +import type {IsEqual} from './is-equal.d.ts'; + +type IndicesOfOptions = { + ignoreOptionalModifier?: boolean; + // FromIndex?: number; +}; + +type DefaultIndicesOfOptions = { + ignoreOptionalModifier: false; + // FromIndex: 0; +}; + +export type IndicesOf< + Array_ extends UnknownArray, Item, + Options extends IndicesOfOptions = {}, +> = IsAnyOrNever extends true ? Array_ + : _IndicesOf + >; + +type _IndicesOf< + Array_ extends UnknownArray, Item, + Options extends Required, + F_Index extends number[] = [], + F_Indices extends Array = [], + B_Index extends number[] = [1], + B_Indices extends Array = [], + T_Index extends number = F_Index['length'], +> = + keyof Array_ & `${number}` extends never + + ? Array_ extends readonly [...infer Rest, infer Last] + ? IsEqual extends true + ? _IndicesOf, [Neg, ...B_Indices]> + : _IndicesOf, B_Indices> + + : [ + ...F_Indices, + ...Array_ extends readonly [] ? [] + : IsEqual extends false ? [] + : [Array_[number] | (number & {})], + ...B_Indices, + ] + + : Array_ extends readonly [(infer First)?, ...infer Rest] + ? IsEqual extends true + ? _IndicesOf, [ + ...F_Indices, + ...Options['ignoreOptionalModifier'] extends true ? [T_Index] + : IsOptionalKeyOf extends false ? [T_Index] + : [T_Index?], + ]> + : _IndicesOf, F_Indices> + + : never; + +export {}; diff --git a/source/last-index-of.d.ts b/source/last-index-of.d.ts new file mode 100644 index 000000000..7f7f9d668 --- /dev/null +++ b/source/last-index-of.d.ts @@ -0,0 +1,74 @@ +import type {GreaterThanOrEqual} from './greater-than-or-equal.d.ts'; +import type {ApplyDefaultOptions} from './internal/object.d.ts'; +import type {IsOptionalKeyOf} from './is-optional-key-of.d.ts'; +import type {Inc, Neg, IndexOfOptions} from './index-of.d.ts'; +import type {UnknownArray} from './unknown-array.d.ts'; +import type {IsAnyOrNever} from './internal/type.d.ts'; +import type {LiteralUnion} from './literal-union.d.ts'; +import type {GreaterThan} from './greater-than.d.ts'; +import type {IsEqual} from './is-equal.d.ts'; + +type DefaultLastIndexOfOptions = { + ignoreOptionalModifier: false; + fromIndex: 0; +}; + +type IsLastOptional = + T extends [...infer Rest, (infer _)?] + ? [...Rest] extends T + ? true + : false + : false; + +export type LastIndexOf< + Array_ extends UnknownArray, Item, + Options extends IndexOfOptions = {}, +> = IsAnyOrNever extends true ? Array_ + : _LastIndexOf + >; + +type _LastIndexOf< + Array_ extends UnknownArray, Item, + Options extends Required, + F_Index extends number[] = [], + B_Index extends number[] = [1], + T_Index extends number = never, +> = + number extends Array_['length'] + ? keyof Array_ & `${number}` extends never + + ? Array_ extends readonly [...infer Rest, infer Last] + ? GreaterThan extends true + ? IsEqual extends true ? Neg + : _LastIndexOf, T_Index> + : _LastIndexOf, T_Index> + + : Array_ extends readonly [] ? T_Index + : IsEqual extends false ? T_Index + : LiteralUnion + + : Array_ extends readonly [(infer First)?, ...infer Rest] + ? IsEqual extends true + ? _LastIndexOf, B_Index, F_Index['length'] | ( + Options['ignoreOptionalModifier'] extends true ? never + : IsOptionalKeyOf extends false ? never + : _LastIndexOf, B_Index, T_Index>)> + : _LastIndexOf, B_Index, T_Index> + : never + + : Array_ extends readonly [...infer Rest, (infer Last)?] + ? GreaterThanOrEqual extends true + ? IsEqual extends true ? Required['length'] | ( + Options['ignoreOptionalModifier'] extends true ? never + : IsLastOptional extends false ? never + : _LastIndexOf>) + : _LastIndexOf> + : _LastIndexOf> + : never; + +export {};