You don't have javascript enabled. Good luck! :(

欢迎页

Welcome to Ganace's Blog


欢迎您来到Ganace 的个人博客。

在茫茫互联网的海洋里能够遇见,实在是一份不小的幸运。

诚挚地向您问候一声:您好,朋友!

这里是属于Ganace个人的隐秘小空间,记录了工作学习中遇到的知识点与灵感,以及生活中的碎碎念与吐槽突如其来的中二病尬尬的文艺时间锻炼腹肌的时刻惊喜的小发现等等。

想要在自己的平淡无奇的人生长河中留下些什么,

或者只是为了拯救老人家岌岌可危的记忆力,

仅此而已。

来到此地,分享与你。

也期待与您的再次相遇!

Share with Me


有任何的分享或者建议与吐槽,都可以Email我:ganace@foxmail.com

欢迎您的来信!

【TypeScript】TypeScript类型体操(十一) 中等挑战

  Mar 28, 2024     Ganace     Front-end-Foundation

TypeScript

TypeScript 的类型体操笔记,温故知新。

斐波那契序列AllCombinationsGreaterThan

ZipIsTupleChunk


中等挑战

一、斐波那契序列

Implement a generic Fibonacci<T> takes an number T and returns it’s corresponding Fibonacci number.

The sequence starts: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …

For example:

type Result1 = Fibonacci<3>; // 2
type Result2 = Fibonacci<8>; // 21

Answer:

type Fibonacci<T extends number, CurrentIndex extends any[] = [1], Prev extends any[] = [], Current extends any[] = [1]> = CurrentIndex["length"] extends T
    ? Current["length"]
    : Fibonacci<T, [...CurrentIndex, 1], Current, [...Prev, ...Current]>;

二、AllCombinations

Implement type AllCombinations<S> that return all combinations of strings which use characters from S at most once.

For example:

type AllCombinations_ABC = AllCombinations<"ABC">;
// should be '' | 'A' | 'B' | 'C' | 'AB' | 'AC' | 'BA' | 'BC' | 'CA' | 'CB' | 'ABC' | 'ACB' | 'BAC' | 'BCA' | 'CAB' | 'CBA'

Answer:

type StrToUnion<S> = S extends `${infer F}${infer R}` ? F | StrToUnion<R> : never;
type AllCombinations<S extends string, U extends string = StrToUnion<S>> = [U] extends [never] ? "" : "" | { [K in U]: `${K}${AllCombinations<never, Exclude<U, K>>}` }[U];

三、GreaterThan

In This Challenge, You should implement a type GreaterThan<T, U> like T > U

Negative numbers do not need to be considered.

For example

GreaterThan<2, 1>; //should be true
GreaterThan<1, 1>; //should be false
GreaterThan<10, 100>; //should be false
GreaterThan<111, 11>; //should be true

Answer:

type ParseInt<T> = T extends `${infer X extends number}` ? X : never;

type RemoveLeadingZeros<T extends string> = T extends "0" ? T : T extends `${0}${infer Rest}` ? RemoveLeadingZeros<Rest> : T;

type InnerMinusOne<T extends string> = T extends `${infer X extends number}${infer Y}` ? (X extends 0 ? `9${InnerMinusOne<Y>}` : `${[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8][X]}${Y}`) : "";

type Reverse<T extends string> = T extends `${infer X}${infer Y}` ? `${Reverse<Y>}${X}` : "";

type MinusOne<T extends number> = ParseInt<RemoveLeadingZeros<Reverse<InnerMinusOne<Reverse<`${T}`>>>>>;

type InnerGreaterThan<T extends number, U extends number> = T extends U ? true : T extends 0 ? false : InnerGreaterThan<MinusOne<T>, U>;

type GreaterThan<T extends number, U extends number> = T extends U ? false : U extends 0 ? true : InnerGreaterThan<T, U>;

四、Zip

In This Challenge, You should implement a type Zip<T, U>, T and U must be Tuple

type exp = Zip<[1, 2], [true, false]> // expected to be [[1, true], [2, false]]

type Zip<T, U, Rt extends unknown[] = []> = T extends [infer F1, ...infer R1] ? (U extends [infer F2, ...infer R2] ? Zip<R1, R2, [...Rt, [F1, F2]]> : Rt) : Rt;

五、IsTuple

Implement a type IsTuple, which takes an input type T and returns whether T is tuple type.

For example:

type case1 = IsTuple<[number]>; // true
type case2 = IsTuple<readonly [number]>; // true
type case3 = IsTuple<number[]>; // false

Answer:

type IsTuple<T> = [T] extends [never] ? false : T extends readonly any[] ? (number extends T["length"] ? false : true) : false;

六、Chunk

Do you know lodash? Chunk is a very useful function in it, now let’s implement it. Chunk<T, N> accepts two required type parameters, the T must be a tuple, and the N must be an integer >=1

For example:

type exp1 = Chunk<[1, 2, 3], 2>; // expected to be [[1, 2], [3]]
type exp2 = Chunk<[1, 2, 3], 4>; // expected to be [[1, 2, 3]]
type exp3 = Chunk<[1, 2, 3], 1>; // expected to be [[1], [2], [3]]

Answer:

type Chunk<T extends any[], U extends number = 1, S extends any[] = []> = T extends [infer F, ...infer R]
    ? S["length"] extends U
        ? [S, ...Chunk<T, U>]
        : Chunk<R, U, [...S, F]>
    : S["length"] extends 0
    ? S
    : [S];