type FirstUniqueCharIndex<T extends string, A extends string[] = [], Idx extends any[] = []> = T extends `${infer F}${infer Rest}`
? F extends A[number] // 检查 F 是否在 A 中
? FirstUniqueCharIndex<Rest, A, [...Idx, unknown]> // 如果是,继续递归并增加索引
: Rest extends `${string}${F}${string}` // 检查 F 是否在剩余字符串中
? FirstUniqueCharIndex<Rest, [...A, F], [...Idx, unknown]> // 如果是,标记 F 为访问过
: Idx['length'] // 否则,返回当前索引(第一个唯一字符的位置)
: -1; // 如果递归到末尾,返回 -1(没有唯一字符)
Solution by wendao-liu #35095
// 你的答案
type FirstUniqueCharIndex<T extends string, Res extends any[] = []> = T extends '' ? -1 :
T extends `${infer A}${infer R}` ?
R extends `${infer _}${A}${infer _}` ? FirstUniqueCharIndex<R, [...Res, A]> :
A extends Res[number] ? FirstUniqueCharIndex<R, [...Res, A]> : Res['length']
: -1
Solution by heyuelan #34724
// if T includes S, return true
type Includes<T extends string, U extends string> = T extends `${infer F}${infer R}`
? F extends U
? true
: Includes<R, U>
: false;
type StringToTuple<S extends string> = S extends `${infer F}${infer R}`
? [F, ...StringToTuple<R>]
: [];
type FirstUniqueCharIndex<
T extends string,
S extends string = ""
> = T extends `${infer F}${infer R}`
? Includes<`${S}${R}`, F> extends true
? FirstUniqueCharIndex<R, `${S}${F}`>
: StringToTuple<S>["length"]
: -1;
Solution by yukicountry #34348
type FirstUniqueCharIndex<T extends string, U extends string[] = []> = T extends '' ? -1 :
T extends `${infer R}${infer rest}` ?
R extends U[number] ? FirstUniqueCharIndex<rest, [...U, R]> :
rest extends `${string}${R}${string}` ? FirstUniqueCharIndex<rest, [...U, R]> :
U['length'] : never
Solution by ouzexi #34110
type FirstUniqueCharIndex<T extends string, L extends string = '', Count extends any[] = []> = T extends `${infer F}${infer Rest}`
? Rest extends `${string}${F}${string}`
? FirstUniqueCharIndex<Rest, `${L}${F}`, [...Count, 1]>
: L extends `${string}${F}${string}`
? -1
: Count['length']
: -1
Solution by PiligrimStas #33798
key point is find the ${Head}${Tail}
extends ${any}${Char}${any}
Head + Char + Tail = T
type FirstUniqueCharIndex<
T extends string,
Head extends string = '',
Count extends any[] = []
> = T extends `${infer Char}${infer Tail}`
? `${Head}${Tail}` extends `${any}${Char}${any}`
? FirstUniqueCharIndex<Tail, `${Head}${Char}`, [...Count, 1]>
: Count['length']
: -1;
Solution by sunupupup #33444
type Includes<T extends string, U extends string> = T extends `${string}${U}${string}` ? true : false;
type LengthOfString<S extends string, A extends string[] = []> = S extends `${infer U}${infer Rest}`
? LengthOfString<Rest, [U, ...A]>
: A['length'];
type FirstUniqueCharIndex<T extends string, Prefix extends string = ''> = T extends `${infer F}${infer R}`
? Includes<`${Prefix}${R}`, F> extends true
? FirstUniqueCharIndex<R, `${Prefix}${F}`>
: LengthOfString<Prefix>
: -1;
Solution by kscory #33080
type FirstUniqueCharIndex<
T extends string,
U extends string = T,
V extends unknown[] = []
> = T extends `${infer First}${infer Rest}`
? U extends `${string}${First}${string}${First}${string}`
? FirstUniqueCharIndex<Rest, U, [...V, unknown]>
: V['length']
: -1;
Solution by Robinsstudio #32940
type StringToTuple<T extends string, Acc extends string[] = []> = T extends `${infer F}${infer R}`
? StringToTuple<R, [...Acc, F]>
: Acc
type FirstUniqueCharIndex<T extends string, VisitedChars extends string[] = []> = T extends `${infer F}${infer R}`
? F extends StringToTuple<R>[number] | VisitedChars[number]
? FirstUniqueCharIndex<R, [...VisitedChars, F]>
: VisitedChars['length']
: -1
Solution by keyurparalkar #32654
// your answers
type FirstUniqueCharIndex<
T extends string,
A extends string = "",
I extends number[] = []
> = T extends `${infer F}${infer L}`
? `${A}${L}` extends `${string}${F}${string}`
? FirstUniqueCharIndex<L, `${A}${F}`, [...I, 1]>
: I["length"]
: -1;
Solution by GodCount #32429
type FirstUniqueCharIndex<
T extends string,
C extends 0[] = [],
P extends string = ""
> = T extends `${infer F}${infer R}`
? `${P}${R}` extends `${string}${F}${string}`
? FirstUniqueCharIndex<R, [...C, 0], `${P}${F}`>
: C["length"]
: -1;
Solution by vangie #32207
// your answers
type FirstUniqueCharIndex<T extends string, C extends any[] = [], U = T> =
T extends `${infer S}${infer O}` ?
(U extends `${infer Q}${S}${O}` ?
(Q extends `${string}${S}${string}` ? FirstUniqueCharIndex<O, [1, ...C], U> :
O extends `${string}${S}${string}` ? FirstUniqueCharIndex<O, [1, ...C], U> : C['length'])
: never)
: -1;
Solution by tarotlwei #31745
type StrToTuple<S extends string> = S extends `${infer F}${infer Rest}`
? [F, ...StrToTuple<Rest>]
: []
type FirstUniqueCharIndex<
T extends string,
L extends string = '',
C extends any[] = [],
> = T extends `${L}${infer S}${infer Rest}`
? S extends StrToTuple<`${L}${Rest}`>[number]
? FirstUniqueCharIndex<T, `${L}${S}`, [...C, any]>
: C['length']
: -1
Solution by Minato1123 #31150
// your answers
type UniqueChars<T extends string, Used = never, UsedMoreThanOnce = never> = T extends `${infer F}${infer Rest}` ? UniqueChars<Rest, Used | F, F extends Used ? UsedMoreThanOnce | F : UsedMoreThanOnce> : Exclude<Used, UsedMoreThanOnce>
type FirstUniqueCharIndex<T extends string, Counter extends never[] = [], U = UniqueChars<T>> = T extends `${infer F}${infer Rest}` ? F extends U ? Counter["length"] : FirstUniqueCharIndex<Rest, [never, ...Counter], U> : -1
UniqueChars<T>
returns the unique characters in T
as a union of characters.
(The core part of this is Exclude<Used, UsedMoreThanOnce>
).
In FirstUniqueCharIndex<T extends string, Counter extends never[] = [], U = UniqueChars<T>>
, we can check whether infer F
is unique by using F extends U
.
The optional argument U
is set to save the result of UniqueChars<T>
.
Solution by Kakeru-Miyazaki #30896
type StringToUnion<S extends string, V extends any[] = []> = S extends `${infer First}${infer Rest}`
? StringToUnion<Rest, [...V, First]>
: V[number];
type FirstUniqueCharIndex<S extends string, T extends unknown[] = []> = S extends `${infer F}${infer Rest}`
? F extends StringToUnion<Rest> | T[number]
? FirstUniqueCharIndex<Rest, [...T, F]>
: T['length']
: -1;
Solution by leejaehyup #30863
// 你的答案
type FirstUniqueCharIndex<T extends string, A extends string = '', U extends string[] = []> = T extends `${infer F}${infer R}` ? `${A}${R}` extends `${any}${F}${any}` ? FirstUniqueCharIndex<R, `${A}${F}`, [...U, '']> : U['length'] : -1
Solution by YE840926098 #30135
利用Count来存储从L中排出的L,当R中不存在L并且Count中也不存在L时,则说明他是唯一的
type FirstUniqueCharIndex<T extends string, Count extends string[] = []> =
T extends `${infer L}${infer R}`
? R extends `${string}${L}${string}`
? FirstUniqueCharIndex<R, [...Count, L]> : L extends Count[number]
? FirstUniqueCharIndex<R, [...Count, L]> : Count['length']
: -1
Solution by sv-98-maxin #30125
type FirstUniqueCharIndex<
T extends string,
Res extends Array<string> = []
> = T extends `${infer Char}${infer Rest}`
? Char extends Res[number]
? FirstUniqueCharIndex<Rest, [...Res, Char]>
: Rest extends `${string}${Char}${string}`
? FirstUniqueCharIndex<Rest, [...Res, Char]>
: Res["length"]
: -1;
Solution by DoubleWoodLin #28850
type UpdateRes<
T extends Array<[string, number]>,
U extends string
> = T extends [infer Item, ...infer Rest extends Array<[string, number]>]
? Item extends [U, infer Index]
? Rest
: [Item, ...UpdateRes<Rest, U>]
: [];
type FirstUniqueCharIndex<
T extends string,
Union extends string = "",
Res extends Array<[string, number]> = [],
Count extends unknown[] = []
> = T extends `${infer Char}${infer Rest}`
? Char extends Union
? FirstUniqueCharIndex<
Rest,
Union,
UpdateRes<Res, Char>,
[unknown, ...Count]
>
: FirstUniqueCharIndex<
Rest,
Union | Char,
[...Res, [Char, Count["length"]]],
[unknown, ...Count]
>
: Res extends []
? -1
: Res[0][1];
Solution by DoubleWoodLin #28849
type FirstUniqueCharIndex<
Chars extends string,
ProcessedChars extends string = "",
ProcessedCharArray extends string[] = []
> = Chars extends `${infer Head}${infer Tail}`
? `${ProcessedChars}${Tail}` extends `${string}${Head}${string}`
? FirstUniqueCharIndex<
Tail,
`${ProcessedChars}${Head}`,
[...ProcessedCharArray, Head]
>
: ProcessedCharArray["length"]
: -1;
Solution by yevhenpavliuk #28412
有点蠢但是思路还算清晰,但是算法上来看性能可能不好?
遍历字符串 s,通过 ${infer F}${infer E}
获取到第一项 F 字符,计算一下 F 字符在字符串 s 中有多少个,这里写了个 RepeatCharCount 类型来计算。
如果只有一个,那么久说明是第一个非重复字符,返回索引。
那么这里就需要记录索引,这种记录索引的,就只能通过数组 length 来处理,通过不断为数组添加元素,来得到当前是第几个
还需要注意的一点是,这里引入了第三个变量 O,用来保存原始的字符串 s,因为每次遍历的字符,都应该判断的是在字符串 s 中的个数
type RepeatCharCount<T extends string, U extends string, N extends any[] = []> = U extends `${infer F}${infer E}`
? T extends F
? RepeatCharCount<T, E, [...N, '']>
: RepeatCharCount<T, E, [...N]>
: N['length']
type FirstUniqueCharIndex<T extends string, N extends string[] = [], O extends string = T> = T extends `${infer F}${infer E}`
? RepeatCharCount<F, O> extends 1
? N['length']
: FirstUniqueCharIndex<E, [...N, ''], T>
: -1
Solution by linjunc #28151
// your answers
type FirstUniqueCharIndex<
T extends string,
U = T,
A extends 0[] = []
> = T extends `${infer L}${infer R}`
? U extends `${string}${L}${string}${L}${string}`
? FirstUniqueCharIndex<R, T, [...A, 0]>
: A["length"]
: -1;
Solution by youpy #27968
type IsUnique<T, F> = T extends true ? (F extends true ? true : false) : false;
type IsPrevRepeat<P extends string[], T> = T extends P[number] ? false : true;
type IsRestRepeat<R, T extends string> = R extends `${string}${T}${string}`
? false
: true;
type FirstUniqueCharIndex<
T extends string,
P extends string[] = []
> = T extends `${infer F}${infer R}`
? IsUnique<IsPrevRepeat<P, F>, IsRestRepeat<R, F>> extends true
? P["length"]
: FirstUniqueCharIndex<R, [...P, F]>
: -1;
never give up on your dream!
Solution by DoGukKim #27896
type Or<A, B> = A extends true ? true : B extends true ? true : false;
type Extends<T, U> = T extends U ? true : false;
type FirstUniqueCharIndex<
T extends string,
Skipped extends unknown[] = [],
Seen extends string = never
> = T extends `${infer L}${infer Rest}`
? Or<Extends<L, Seen>, Extends<Rest, `${any}${L}${any}`>> extends true
? FirstUniqueCharIndex<Rest, [...Skipped, L], Seen | L>
: Skipped["length"]
: -1;
Solution by alythobani #27620
type FirstUniqueCharIndex<T extends string, B extends string[] = []> =
T extends `${infer F}${infer R}`
? `${R}` extends `${string}${F}${string}`
? FirstUniqueCharIndex<R, [...B, F]>
: F extends B[number]
? FirstUniqueCharIndex<R, [...B, F]>
: B['length']
: -1;
Solution by smileboyi #27215
type OneByString<T extends string, U extends string, i extends number[] = []> = T extends `${infer S}${infer R}` ? S extends U ? OneByString<R, U, [...i, 0]> : OneByString<R, U, i> : i['length']
type FirstUniqueCharIndex<T extends string,N extends string = T ,i extends string[] = []> = N extends `${infer S}${infer R}` ? OneByString<T, S> extends 1
? i['length'] : FirstUniqueCharIndex<T,R,[...i, S]> : -1
Solution by WangZiChu199910252255 #26903
type FirstUniqueCharIndex<T extends string, U extends any[] = []> =
T extends `${infer L}${infer R}`
? R extends `${any}${L}${any}`
? FirstUniqueCharIndex<R, [...U, L]>
: L extends U[number] ? FirstUniqueCharIndex<R, [...U, L]> : U['length']
: -1;
Solution by omittee #26693
// your answers
type StringToTuple<T, C extends unknown[] = []> = T extends '' ? C : T extends ${infer F}${infer R}
? StringToTuple<R, [...C, F]> : never
type StingToUnion${infer F}${infer R}
? F extends StingToUnion<${PRE}${R}
>
? FirstUniqueCharIndex<R, [...C, 1], ${PRE}${F}
>
: C["length"]
: never
Solution by enochjs #26316
// your answers
type FirstUniqueCharIndex<
S,
Prefix extends string = "",
Index extends never[] = []
> = S extends `${infer F}${infer Rest}`
? `${Prefix}${Rest}` extends `${infer A}${F}${infer B}`
? FirstUniqueCharIndex<Rest, `${Prefix}${F}`, [...Index, never]>
: Index["length"]
: -1;
Solution by DvYinPo #25901
// your answers
type FirstUniqueCharIndex<T extends string, Cur extends unknown[] = [], Prev extends string = ''> =
T extends `${infer X}${infer Y}`
? Y extends `${infer A}${X}${infer B}`
? FirstUniqueCharIndex<Y, [...Cur, X], `${Prev}${X}`>
: Prev extends `${infer A}${X}${infer B}`
? FirstUniqueCharIndex<Y, [...Cur, X], `${Prev}${X}`>
: Cur['length']
: -1
Solution by kiki-zjq #25764