05153-medium-indexof

Back

type IsEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;
type IndexOf<T extends any[], U extends number | string, A extends any[] = []> = T extends [infer F, ...infer Rest] ? IsEqual<F, U> extends true ? A['length'] : IndexOf<Rest, U, [...A, 0]> : -1

Solution by wendao-liu #35075

// 你的答案
type isAny<T> = 0 extends T ? '1' extends T ? true : false : false
type IndexOf<T, U, Res extends any[] = []> = T extends [infer A, ...infer R] ? 
  isAny<U> extends true ? isAny<A> extends true ? Res['length'] : IndexOf<R, U, [...Res, A]> : 
  isAny<A> extends true ? IndexOf<R, U, [...Res, A]> :
  [A, U] extends [U, A] ? Res['length'] : IndexOf<R, U, [...Res, A]> 
  : -1

Solution by heyuelan #34722

// this type take two type parameters (T: tuple, V: any value), and returns tuple which has items until first appearance of V
// eg. TruncateTupleByValue<[1, 2, 3], 3> produces [1, 2]
type TruncateTupleByValue<T extends unknown[], V> = T extends [infer F, ...infer R]
  ? Equal<F, V> extends true
    ? []
    : [F, ...TruncateTupleByValue<R, V>]
  : [];

// index of U corresponds to the length of truncated tuple
// if length of truncated tuple is identical to original one, U does not exist in T, and should return -1 
type IndexOf<T extends unknown[], U> = TruncateTupleByValue<T, U> extends [...infer S]
  ? S extends T
    ? -1
    : S["length"]
  : never;

Solution by yukicountry #34342

type IndexOf<T extends any[], U extends number | string, K extends any[] = []> = T extends [infer R, ...infer rest] ? Equal<R, U> extends true ? K['length'] : IndexOf<rest, U, [...K, 1]> : -1

Solution by ouzexi #34092

5153 - IndexOf

by Pineapple (@Pineapple0919) #medium #array

Question

Implement the type version of Array.indexOf, indexOf<T, U> takes an Array T, any U and returns the index of the first U in Array T.

type Res = IndexOf<[1, 2, 3], 2>; // expected to be 1
type Res1 = IndexOf<[2,6, 3,8,4,1,7, 3,9], 3>; // expected to be 2
type Res2 = IndexOf<[0, 0, 0], 2>; // expected to be -1

View on GitHub: https://tsch.js.org/5153

...


type IndexOf<T extends unknown[], U extends unknown, N extends number[] = []> = T extends [infer L, ...infer R]
  ? Equal<U, L> extends true
    ? N['length']
    : IndexOf<R, U, [1, ...N]>
  : -1

Solution by veralex #33838

type isEqual<T, U> = T extends U ? U extends T ? true : never : never

type isAny<T> = T extends never ? true : never

type Compare<T, U> = isAny<T> extends never ? isAny<U> extends never ? isEqual<T, U> : false : isAny<U> extends never ? false : true

type IndexOf<T extends any[], U, Arr extends any[] = []> = T['length'] extends Arr['length']
? -1
: true extends Compare<U, T[Arr['length']]>
  ? Arr['length']
  : IndexOf<T, U, [...Arr, 1]>

Solution by PiligrimStas #33777

type IndexOf<
  T extends any[],
  U extends any,
  Temp extends any[] = []
> = T extends [infer First, ...infer Rest extends any[]]
  ? SimpleEqual<First, U> extends true
    ? Temp['length']
    : IndexOf<Rest, U, [1, ...Temp]>
  : -1;

type SimpleEqual<T1, T2> = T1 extends T2
  ? T2 extends T1
    ? true
    : false
  : false;

Solution by sunupupup #33418

export type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false

type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N

type IndexOf<T extends unknown[], U extends unknown, R extends unknown[] = []> = 
  T extends [infer F, ...infer Rest] ?
  Equal<U, F> extends true ?
  IfAny<F, 
  IfAny<U, R['length'], IndexOf<Rest, U, [...R, true]>>, 
  IfAny<U,IndexOf<Rest, U, [...R, true]>, R['length']>> :
  IndexOf<Rest, U, [...R, true]> :
  -1

type cases = [
  Expect<Equal<IndexOf<[1, 2, 3], 2>, 1>>,
  Expect<Equal<IndexOf<[2, 6, 3, 8, 4, 1, 7, 3, 9], 3>, 2>>,
  Expect<Equal<IndexOf<[0, 0, 0], 2>, -1>>,
  Expect<Equal<IndexOf<[string, 1, number, 'a'], number>, 2>>,
  Expect<Equal<IndexOf<[string, 1, number, 'a', any], any>, 4>>,
  Expect<Equal<IndexOf<[string, 'a'], 'a'>, 1>>,
  Expect<Equal<IndexOf<[any, 1], 1>, 1>>,
]

Solution by gearonixx #30924

type IndexOf<T extends readonly any[], U, I extends any[] = []> = 
  T extends [infer F, ...infer R]
    ? Equal<F,U> extends true
      ? I['length']
      : IndexOf<R, U, [...I, 0]>
    : -1

Solution by matallui #30811

type IndexOf<T, U, O extends any[] = []> = T extends [infer A, ...infer B] ? Equal<A, U> extends true ? O['length']: IndexOf<B, U, [...O, A]> : -1

Solution by dreamluo-plus #30662

type IndexOf<T extends unknown[], U extends unknown, C extends unknown[] = []> =
  T extends [infer A, ...infer RA]
    ? 
      Equal<A, U> extends true
        ?
          C['length']
        : IndexOf<RA, U, [...C, A]>
      : -1

Solution by zhangqiangzgz #30199

   type IndexOf<T extends any[], E, R extends any[] = []> = R['length'] extends T['length'] ? -1 : T[R['length']] extends E ?
    R['length'] : IndexOf<T, E, [...R, 0]>;

type indexOf = IndexOf<[1, 2, 3], 2>;

const index: indexOf = 1;

Solution by sundial-dreams #29548

type IsEqual<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B
  ? 1
  : 2
  ? true
  : false;
  
type IndexOf<T, U, Count extends unknown[] = []> = T extends [
  infer F,
  ...infer R
]
  ? IsEqual<F, U> extends true
    ? Count["length"]
    : IndexOf<R, U, [...Count, unknown]>
  : -1;

Solution by DoubleWoodLin #28779

type IsEqual<X, Y> = X extends Y ? Y extends X ? true : false : false;
type FirstValue<T extends any[]> = T extends [] ? never : T extends [infer R, ...infer _] ? R : never;
type ShiftRest<T extends any[]> = T extends [] ? [] : T extends [infer _, ...infer R] ? R : never;
type Pop<T extends any[]> = T extends [] ? [] : T extends [...infer R, infer _] ? R : never;
type SliceFromStart<T extends any[], U> = IsEqual<FirstValue<T>, U> extends true ?  [FirstValue<T>] : [FirstValue<T>, ...(SliceFromStart<ShiftRest<T>, U>)]
type Len<T extends any[], U> = Pop<SliceFromStart<T, U>>["length"];
type IndexOf<T extends any[], U> = Len<T, U> extends T["length"] ? -1 : Len<T, U>;

Solution by breakinferno #28424

type IsEqual<A, B> = (<X>() => X extends A ? 1 : 2) extends <X>() => X extends B
  ? 1
  : 2
  ? true
  : false;

// 思路:构建一个元组类型R,取R的length作为索引,第一次遍历时R为空元组,length为0,以此类推
type IndexOf<T, U, R extends unknown[] = []> = T extends [
  infer F,
  ...infer Rest
]
  ? IsEqual<F, U> extends true
    ? R["length"]
    : IndexOf<Rest, U, [...R, unknown]>
  : -1;

Solution by jiaowoxiaobala #27986

type IndexOf<T extends unknown[], S, V extends unknown[] = []> = T extends []
  ? -1 : Equal<T[0], S> extends true
      ? V['length'] : IndexOf<T extends [unknown, ...infer Next]
        ? Next : [], S, [...V, 1]>

Solution by jiechliu #27802

type IndexOf<T extends any[], I extends number, U extends any[] = []> = T extends [infer N, ...infer Rest] ? N extends I ? U['length'] : IndexOf<Rest, I, [...U, N]> : -1

Solution by HenrryShaw #27761

The solution is too long to fit in an issue, so here's a gist. https://gist.github.com/RuyiLi/344242fc304fb70a562c97a39e67dbee

Solution by RuyiLi #27746

type IndexOf<T extends unknown[], N, C extends unknown[] = []> = T extends [
  infer R,
  ...infer V
]
  ? R extends N
    ? C["length"]
    : IndexOf<V, N, [unknown, ...C]>
  : -1;

Solution by ryuji-1to #27368

type IndexOf<T, U, P extends unknown[] = []> =
  T extends [infer F, ...infer R] ? Equal<F, U> extends true ? P['length'] : IndexOf<R, U, [...P, 1]> : -1

Solution by smileboyi #27108

type IndexOf<T extends unknown[], U, i extends unknown[] = []> = Equal<T[i['length']],U> extends true ? i['length'] : i['length'] extends T['length'] ? -1 : IndexOf<T,U,[...i,T[i['length']]]>

Solution by WangZiChu199910252255 #26897

/**
 * @description judge whether U is equal to T
 */
type isEqual<U, T> = U extends T ? (T extends U ? true : false) : false;

/**
 * @description 获取元组中指定元素的索引
 * @param T 元组
 * @param U 指定元素
 * @param Length 相当于一个计数器,每次递归都会将当前元素推入其中,最后返回Length的长度
 */
type IndexOf<T, U, Length extends unknown[] = []> = T extends [infer First, ...infer Rest]
  ? isEqual<First, U> extends true
    ? Length['length']
    : IndexOf<Rest, U, [...Length, First]>
  : -1;

Solution by Lu9709 #26865

type Equals<A, B> = A extends B ? (B extends A ? true : false) : false;
type IndexOf<T extends unknown[], U extends unknown, COUNT extends 0[] = []> = T extends [infer Head, ...infer Tail] ? Equals<U,Head> extends true ? COUNT['length'] : IndexOf<Tail,U, [...COUNT,0]> :  -1

Solution by ScarboroughCoral #26506

type IndexOf<T extends unknown[], U, Res extends unknown[] = []> = 
  T extends [infer F, ...infer R] 
  ? Equal<F, U> extends true
    ? Res['length']
    : IndexOf<R, U, [...Res, 0]>
  : -1```

Solution by liuk123456789 #26127

// your answers
type MyEqual<X, Y> = 
  X extends Y 
  ? Y extends X 
    ? true
    : false
  : false 

type IndexOf<T extends unknown[], U extends unknown, Arr extends unknown[] = []> = 
  T extends [infer X, ...infer Y]
  ? MyEqual<X, U> extends true 
    ? Arr['length']
    : IndexOf<Y, U, [unknown, ...Arr]>
  : -1

Solution by kiki-zjq #25669

type IndexOf<
  T extends unknown[],
  U,
  Acc extends unknown[] = []
> = T extends [infer First, ...infer Rest]
? Equal<First, U> extends true
  ? Acc['length']
  : IndexOf<Rest, U, [...Acc, 1]>
: -1

Solution by NeylonR #24273

// your answers
type MyEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y
    ? 1
    : 2
    ? true
    : false
type IndexOf<
    T extends any[],
    U,
    Index extends any[] = []
> = T['length'] extends Index['length']
    ? -1
    : MyEqual<T[Index['length']], U> extends true
    ? Index['length']
    : IndexOf<T, U, [...Index, any]>

Solution by studymachiney #24113

type IndexOf<T extends any[], U, _Counter extends 1[] = []> = T extends [infer F, ...infer R] ?
  Equal<F, U> extends true ? _Counter[`length`]/*return*/ : IndexOf<R, U, [..._Counter, 1]> :
  -1/*return*/;

// old way
// type SimpleEqual<T, U> = T extends U ? U extends T ? true : false : false;
// type IndexOf<T extends any[], U, _Counter extends any[] = []> =
//   T extends [] ? -1 :
//   (
//     SimpleEqual<U, T[0]> extends true ?
//     _Counter["length"] :
//     (
//       T extends [any, ...infer R] ? IndexOf<R, U, [..._Counter, unknown]> : T
//     )
//   );

Solution by E-uler #23985

type isEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false

type IndexOf<T extends unknown[], U, S extends unknown[] = []> = T extends [infer L, ...infer Rest] ? isEqual<L, U> extends true ? S['length'] : IndexOf<Rest, U, [...S, L]> : -1;

Solution by asurewall #23133

type IndexOf<T extends unknown[], U, Acc extends unknown[] = []> = T extends [infer F, ...infer R] ? 
Equal<U, F> extends true ? [...Acc]['length'] : IndexOf<R, U, [...Acc, F]> : -1

Solution by snakeUni #23118