type IsPalindrome<T extends number | string> = `${T}` extends `${infer First}${string}`
? `${T}` extends `${First}${infer Rest}${First}`
? IsPalindrome<Rest>
: T extends First ? true : false
: true
Solution by 2083335157 #35064
type IsPalindrome<T extends string | number> = `${T}` extends `${infer R}${infer rest}` ? rest extends '' ? true : (`${T}` extends `${R}${infer S}${R}` ? IsPalindrome<S> : false) : true
Solution by ouzexi #34305
type IsPalindrome<T extends number | string> =
`${T}` extends `${infer R}${infer Tail}`
? Tail extends ""
? true
: `${T}` extends `${R}${infer Mid}${R}`
? IsPalindrome<Mid>
: false
: true;
Solution by Vampirelee #32643
type IsPalindrome<T extends number | string> =
`${T}` extends `${infer L}${infer R}`
? R extends `${infer S}${L}`
? S extends '' ? true : IsPalindrome<S>
: R extends '' ? true : false
: never
Solution by vangie #32257
type Str2Arr<T> = T extends `${infer A}${infer B}` ? [A, ...Str2Arr<B>] : []
type IsPalindrome<T extends string | number, O = Str2Arr<`${T}`>> = O extends [infer A, ...infer B, infer C] ? A extends C ? IsPalindrome<T, B> : false : true
Solution by dreamluo-plus #30776
// your answers
type IsPalindromeAry<Ary> =
Ary extends unknown[] ?
Ary extends []
? true
: Ary['length'] extends 1
? true
: Ary extends [infer Head, ...infer Mid, infer Last] ? Head extends Last ? IsPalindromeAry<Mid> : false : false: false
Solution by 437204933 #29708
type StrToArr<T extends string> = T extends `${infer Item}${infer R}`
? [Item, ...StrToArr<R>]
: [];
type IsPalindrome<T extends number | string, U = StrToArr<`${T}`>> = U extends [
infer L,
...infer Rest,
infer R
]
? L extends R
? IsPalindrome<T, Rest>
: false
: true;
Solution by DoubleWoodLin #28944
type IsPalindrome<T extends string | number> = `${T}` extends ''
? true
: `${T}` extends `${infer First}${infer Rest}`
? Rest extends ''
? true
: Rest extends `${infer Middle}${First}`
? IsPalindrome<Middle>
: false
: false
Solution by aybykovskii #28917
type Reverse<T extends string | number | bigint, _R extends string = ''> =
`${T}` extends `${infer First}${infer Rest}` ? Reverse<Rest, `${First}${_R}`> : _R
type IsPalindrome<T extends string | number> = `${T}` extends Reverse<T> ? true : false
Solution by jjswifty #27719
type IsPalindrome<S extends string | number> = `${S}` extends `${infer S0}${infer SRest}` ? (
SRest extends `${infer SBody}${S0}` | '' ? IsPalindrome<SBody> : false
) : true
Solution by BOCbMOU #27003
Supports mixed case phrases like "Mr. Owl ate my metal worm!"
type LowerCaseAlphabet =
| "a"
| "b"
| "c"
| "d"
| "e"
| "f"
| "g"
| "h"
| "i"
| "j"
| "k"
| "l"
| "m"
| "n"
| "o"
| "p"
| "q"
| "r"
| "s"
| "t"
| "u"
| "v"
| "w"
| "x"
| "y"
| "z";
type Alphabet = LowerCaseAlphabet | Uppercase<LowerCaseAlphabet>;
type OnlyAlpha<
T,
R extends string = ""
> = T extends `${infer Char}${infer Rest}`
? Char extends Alphabet
? OnlyAlpha<Rest, `${R}${Char}`>
: OnlyAlpha<Rest, R>
: T extends Alphabet
? `${R}${T}`
: R;
type StringToTuple<
T,
R extends Array<string> = []
> = T extends `${infer Char}${infer Rest}`
? StringToTuple<Rest, [...R, Char]>
: R;
type TupleToString<T, R extends string = ""> = T extends [
infer First extends string,
...infer Rest
]
? TupleToString<Rest, `${R}${First}`>
: R;
type IsPalindrome<T extends string> = StringToTuple<
OnlyAlpha<Lowercase<T>>
> extends [infer First, ...infer Middle, infer End]
? First extends End
? IsPalindrome<TupleToString<Middle>>
: false
: true;
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from "@type-challenges/utils";
type cases = [
// @ts-expect-error
IsPalindrome<unknown>,
// @ts-expect-error
IsPalindrome<1>,
Expect<Equal<IsPalindrome<"a">, true>>,
Expect<Equal<IsPalindrome<"racecar">, true>>,
Expect<Equal<IsPalindrome<"abca">, false>>,
Expect<Equal<IsPalindrome<"deed">, true>>,
Expect<Equal<IsPalindrome<"hello world">, false>>,
Expect<Equal<IsPalindrome<"today">, false>>,
Expect<Equal<IsPalindrome<"Mr. Owl ate my metal worm!">, true>>,
Expect<Equal<IsPalindrome<"Do geese see God?">, true>>
];
Solution by cdierkens #26954
This challenge is just pure fun. It's not terribly difficult (despite being in the hard difficulty group) and it has a lot of interesting solutions: one of which that is guaranteed to make you smile. Who'da thunk checking numbers and strings for being palindromes would be so fun?
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'
type A1 = IsPalindrome<'abc'>;
type B1 = false;
type C1 = Expect<Equal<A1, B1>>;
type A2 = IsPalindrome<'b'>;
type B2 = true;
type C2 = Expect<Equal<A2, B2>>;
type A3 = IsPalindrome<'abca'>;
type B3 = false;
type C3 = Expect<Equal<A3, B3>>;
type A4 = IsPalindrome<'abcba'>;
type B4 = true;
type C4 = Expect<Equal<A4, B4>>;
type A5 = IsPalindrome<121>;
type B5 = true;
type C5 = Expect<Equal<A5, B5>>;
type A6 = IsPalindrome<19260817>;
type B6 = false;
type C6 = Expect<Equal<A6, B6>>;
// // ============= Your Code Here =============
// type IsPalindrome<
// T extends string | number,
// K = `${T}`,
// > =
// K extends `${infer Head}${infer Tail}`
// ? Tail extends ''
// ? true
// : K extends `${Head}${infer Middle}${Head}`
// ? IsPalindrome<Middle>
// : false
// : true;
// // ============== Alternative ==============
// type Reverse<T, Acc extends string = ''> =
// T extends `${infer Head}${infer Tail}`
// ? Reverse<Tail, `${Head}${Acc}`>
// : Acc;
// type IsPalindrome<T extends string | number> =
// `${T}` extends Reverse<`${T}`>
// ? true
// : false;
// ============== Alternative ==============
type StringToTuple<T extends string> =
T extends `${infer Head}${infer Tail}`
? [Head, ...StringToTuple<Tail>]
: [];
type IsIsPalindromeArray<T extends any[]> =
T extends [infer Head, ...infer Middle, infer Tail]
? Head extends Tail
? IsIsPalindromeArray<Middle>
: false
: true;
type IsPalindrome<T extends string | number> =
IsIsPalindromeArray<
StringToTuple<`${T}`>
>;
For more video solutions to other challenges: see the umbrella list! https://github.com/type-challenges/type-challenges/issues/21338
Solution by dimitropoulos #25354
//反转法
type Reverse<T extends string, _Result extends string = ``/*Too Deep Soultion*/> = T extends `${infer F}${infer R}` ? Reverse<R, `${F}${_Result}`> : _Result; //12345 ==> 54321
type IsPalindrome<T extends string | number> = `${T}` extends Reverse<`${T}`> ? true : false;
//靠拢法
// type ToArray<T extends string, _Result extends string[] = []/*Too Deep Soultion*/> = T extends `${infer F}${infer R}` ? ToArray<R, [..._Result, F]> : _Result;
// type DrawClose<T extends any[]> = T extends [infer F, ...infer R, infer L] ? (F extends L ? DrawClose<R> : false) : true; //[a,bcb,a] ==> [b,c,b] ==> [c] ==> [] ==> true
// type IsPalindrome<T extends string | number> = DrawClose<ToArray<`${T}`>>;
Solution by E-uler #24980
type ReverseString<T extends string | number> = `${T}` extends `${infer First}${infer Rest}`
? `${ReverseString<Rest>}${First}`
: T
type IsPalindrome<T extends string | number> = `${T}` extends ReverseString<T> ? true : false
Solution by NeylonR #24529
// your answers
type IsPalindrome<T extends number | string,Z extends string = '',L extends string = ''> =
`${T}` extends `${infer F}${infer R}` ? IsPalindrome<R, `${Z}${F}`, `${F}${L}`> : Equal<Z, L>
Solution by snakeUni #23974
// your answers
type ReverseStr<Str extends string> = Str extends `${infer First}${infer Rest}` ? `${ReverseStr<Rest>}${First}` : '';
type IsPalindrome<T extends number | string> = `${T}` extends ReverseStr<`${T}`> ? true : false;
Solution by jxhhdx #23663
type ToPalindrome<T extends string | number> =
(`${T}` extends `${infer F}${infer R}` ? `${ToPalindrome<R>}${F}` : `${T}`)
type IsPalindrome<T extends string | number> = ToPalindrome<T> extends (`${T}`) ? true : false
It Also Works
type IsPalindrome<T extends string | number, Res extends string | number = T, Result extends string | number = ''> =
`${Res}` extends `${infer F}${infer R}`
? IsPalindrome<T, R, `${F}${Result}`>
: Result extends `${T}` ? true : false
Solution by TKBnice #23369
type IsPalindrome<T extends string | number> =
`${T}` extends `${infer A}${infer B}${infer C}`
? `${B}${C}` extends `${infer D}${A}`
? IsPalindrome<D>
: false
: true
Solution by liuseen-l #23336
type IsPalindrome<T extends string | number> =
`${T}` extends `${infer A}${infer B}${infer R}`
? `${B}${R}` extends `${infer L}${A}`
? IsPalindrome<L>
: false
: true
Solution by drylint #22758
type NumberToString${T}
type ReverseString<T extends string, Result extends string = ''> =
T extends ''
? Result
: T extends ${infer F}${infer Rest}
? ReverseString<Rest, ${F}${Result}
>
: never
type IsPalindrome<T extends string | number> =
T extends number
? NumberToString
Solution by amcguire704 #22491
// infer 2 characters to guarantee that the string or number has at least 2 characters
type IsPalindrome<T extends string | number> = `${T}` extends `${infer Outer}${infer Inner}${infer Right}`
// if the 2nd character with the right side end on the first character from before call this type with the inner part again
? `${Inner}${Right}` extends `${infer Rest}${Outer}` ? IsPalindrome<Rest> :
// if there are less then 2 characters left return true
false : true;
Solution by Karamuto #22214
// infer 2 characters to guarantee that the string or number has at least 2 characters
// if the 2nd character with the right side end on the first character from before call this type with the inner part again
// if there are less then 2 characters left return true
type IsPalindrome<T extends string | number> = `${T}` extends `${infer Outer}${infer Inner}${infer Right}`
? `${Inner}${Right}` extends `${infer Rest}${Outer}` ? IsPalindrome<Rest> :
false : true;
Solution by Karamuto #22213
type Reverse<T> = T extends `${infer A}${infer B}` ? `${Reverse<B>}${A}` : T
type IsPalindrome<T extends string | number>
= `${T}` extends infer S ? Equal<S, Reverse<S>> : 'ahhhhhh~~~'
Solution by goddnsgit #21927
type Reverse<T extends string> =
T extends `${infer First}${infer Rest}`
? `${Reverse<Rest>}${First}`
: T
type IsPalindrome<T extends string | number> =
`${T}` extends Reverse<`${T}`>
? true
: false
Solution by zhaoyao91 #21846
// your answers
//判断首元素和末元素是否相等,
//是则把true就添加进一个数组,并移除首元素和末元素,继续递归判断。
//是若是否则返回false。
//we can compare the first element with the last element ,if they are equal , we can push a true type in a array , and remove
//the first element and the last element , The next step is to proceed with recursive judgment.
//if the first element with the last element are not equal , return false directly.
type GetLastStr<T> = T extends `${infer F}${infer R}` ? R extends '' ? F : GetLastStr<R> : ''
type RemoveLastStr<T,S extends string = ''> = T extends `${infer F}${infer R}` ?
R extends '' ? S : RemoveLastStr<R,`${S}${F}`> : ''
type IsBothTrue<T> = T extends true[] ? true : false
type NumberToStr<N extends number | string> = `${N}`
type IsPalindrome<T extends number | string,Arr extends boolean[] = []> =
NumberToStr<T> extends `${infer F}${infer R}` ? R extends '' ? IsBothTrue<Arr> :
F extends GetLastStr<R> ? IsPalindrome<`${RemoveLastStr<R>}`,Arr extends [...infer Rest] ? [...Rest,true] : []> : false
: true
Solution by YqxLzx #21600
// your answers
// 1. 字符串不能够取首尾值,需要转换成数组
type ToArr<S extends string> = S extends `${infer Head}${infer Rest}` ? [Head, ...ToArr<Rest>] : []
// - 完全遍历完,再进行计算两个 res Arr 是否相等
// type IsPalindrome<T, HeadArr extends any[] = [], EndArr extends any[] = []> = T extends string | number ? IsPalindrome<ToArr<`${T}`>> : T extends [infer Head, ...infer Rest , infer End] ? IsPalindrome<Rest,[...HeadArr,Head], [...EndArr,End]> : HeadArr extends EndArr ? true : false
// - 遍历中计算是否相等
type IsPalindrome<T> = T extends string | number ? IsPalindrome<ToArr<`${T}`>> : T extends [infer Head, ...infer Rest , infer End] ? Head extends End ? IsPalindrome<Rest>: false : true
type res = [1] extends [infer Head, ...infer Rest, infer End] ? [Head, Rest, End]: false
Solution by Rebornjiang #21397
type Join<T extends Array<string>, U extends string | number> = T extends [
infer H extends string,
...infer L extends string[]
]
? `${H}${L extends [] ? "" : U}${Join<L, U>}`
: "";
type stringToArray<
T extends string | number,
Result extends Array<string> = []
> = `${T}` extends `${infer A}${infer B}`
? stringToArray<B, [...Result, A]>
: Result;
type IsPalindrome<T extends string | number> = stringToArray<T> extends [
infer A,
...infer B extends Array<string>,
infer C
]
? A extends C
? IsPalindrome<Join<B, "">>
: false
: true;
Solution by so11y #21252
// version 1
type ToTuple<T extends number | string> = `${T}` extends `${infer F}${infer O}`
? [F, ...ToTuple<O>]
: []
type IsPalindrome<T extends string | number, U = ToTuple<T>> =
U extends [infer L, ...infer M, infer R]
? L extends R
? IsPalindrome<T, M>
: false
: U extends [infer L] ? true : false
// version 2
type Reverse<T extends number | string> = `${T}` extends `${infer F}${infer O}`
? `${Reverse<O>}${F}`
: T
type IsPalindrome<T extends string | number> = `${T}` extends Reverse<T>
? true
: false
Solution by pengzhanbo #20480
Mine.
type Reverse<T extends string | number, _Result extends string = ''> =
`${ T }` extends `${ infer F }${ infer Rest }`
? Reverse<Rest, `${ F }${ _Result }`>
: _Result
type IsPalindrome<T extends string | number> = Reverse<T> extends `${ T }` ? true : false
#16957 better.
Solution by lvjiaxuan #20301
type ToArray<S extends string | number, Result extends string[] = []> = `${S}` extends `${infer F}${infer R}` ? ToArray<R, [...Result, F]> : Result;
type ArrayToReversalString<T extends string[], Total extends string = ''> =
T extends [...infer F extends string[], infer R extends string]
? ArrayToReversalString<F, `${Total}${R}`>
: Total;
type IsPalindrome<T extends string | number> = Equal<`${T}`, ArrayToReversalString<ToArray<T>>>;
Solution by CaoXueLiang #19482