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

欢迎页

Welcome to Ganace's Blog


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

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

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

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

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

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

仅此而已。

来到此地,分享与你。

也期待与您的再次相遇!

Share with Me


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

欢迎您的来信!

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

  Apr 5, 2024     Ganace     Front-end-Foundation

TypeScript

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

统计数组中的元素个数整数将类型为字面类型(标签类型)的属性,转换为基本类型。

DeepMutableAllFilter


中等挑战

一、统计数组中的元素个数

通过实现一个CountElementNumberToObject方法,统计数组中相同元素的个数

For example:

type Simple1 = CountElementNumberToObject<[]>; // return {}
type Simple2 = CountElementNumberToObject<[1, 2, 3, 4, 5]>;
/*
 return {
  1: 1,
  2: 1,
  3: 1,
  4: 1,
  5: 1
}
*/
type Simple3 = CountElementNumberToObject<[1, 2, 3, 4, 5, [1, 2, 3]]>;
/*
 return {
  1: 2,
  2: 2,
  3: 2,
  4: 1,
  5: 1
}
*/

Answer:

// 数组展开
type Flat<T> = T extends [infer A, ...infer B] ? (A extends any[] ? [...Flat<A>, ...Flat<B>] : [A, ...Flat<B>]) : T;
// O为需要计数的项,U收集重复项
type Count<T, O, U extends any[] = []> = T extends [infer A, ...infer B] ? (A extends O ? Count<B, O, [...U, O]> : Count<B, O, [...U]>) : U["length"];
// 统计数组中的元素个数
type CountElementNumberToObject<T extends any[], U extends any[] = Flat<T>> = {
    [K in U[number]]: Count<U, K>;
};

二、整数

请完成类型 Integer<T>,类型 T 继承于 number,如果 T 是一个整数则返回它,否则返回 never
type Integer<T extends number> = number extends T ? never : `${T}` extends `${any}.${any}` ? never : T;

// fantastic way
// type Integer<T extends number> = `${T}` extends `${bigint}` ? T : never

三、将类型为字面类型(标签类型)的属性,转换为基本类型。

将类型为字面类型(标签类型)的属性,转换为基本类型。

type PersonInfo = { name: 'Tom', age: 30, married: false, addr: { home: '123456', phone: '13111111111' } }

// 要求结果如下: type PersonInfo = { name: string, age: number, married: boolean, addr: { home: string, phone: string } }

type ToPrimitive<T> = T extends object
    ? T extends (...args: never[]) => unknown
        ? Function
        : {
              [Key in keyof T]: ToPrimitive<T[Key]>;
          }
    : // 如果 T 是一个包装对象类型,如 Number 或 String 类型,它会具有一个 valueOf 方法返回对应的原始类型。T 是原始类型,直接返回 T
    T extends { valueOf: () => infer P }
    ? P
    : T;

四、DeepMutable

实现一个通用的 DeepMutable ,它使对象的每个属性,及其递归的子属性 - 可变。

例如:

type X = {
    readonly a: () => 1;
    readonly b: string;
    readonly c: {
        readonly d: boolean;
        readonly e: {
            readonly g: {
                readonly h: {
                    readonly i: true;
                    readonly j: "s";
                };
                readonly k: "hello";
            };
        };
    };
};

type Expected = {
    a: () => 1;
    b: string;
    c: {
        d: boolean;
        e: {
            g: {
                h: {
                    i: true;
                    j: "s";
                };
                k: "hello";
            };
        };
    };
};
type Todo = DeepMutable<X>; // should be same as `Expected`

你可以假设我们在这个挑战中只处理对象。 数组、函数、类等不需要考虑。 但是,您仍然可以通过涵盖尽可能多的不同案例来挑战自己。

type DeepMutable<T> = T extends Record<string, any>
  ? {
  - readonly [K in keyof T]: T[K] extends Record<string, any> 
    ? T[K] extends (...args: any[]) => any
      ? T[K]
      : DeepMutable<T[K]>
    : T[K]
} : T
type DeepMutable<T extends Record<keyof any, any>> =
  T extends (...args: any[]) => any ?
  T :
  {
    - readonly [K in keyof T]: DeepMutable<T[K]>
  }

五、All

Returns true if all elements of the list are equal to the second parameter passed in, false if there are any mismatches.

For example:

type Test1 = [1, 1, 1]
type Test2 = [1, 1, 2]

type Todo = All<Test1, 1> // should be same as true
type Todo2 = All<Test2, 1> // should be same as false

Answer:

type IsEqual<T, U> = T extends U ? U extends T ? true : false : false;

type All<T extends unknown[], K, Flag extends boolean = false> =
  T extends [infer L, ...infer R]
  ? IsEqual<L, K> extends true
    ? All<R, K, true>
    : false
  : Flag

六、Filter

Implement the type Filter<T, Predicate> takes an Array T, primitive type or union primitive type Predicate and returns an Array include the elements of Predicate.

For example:

Filter<[0, 1, 2], 2>;// [2]
Filter<[0, 1, 2], 0 | 1>;// [0, 1]
Filter<[0, 1, 2], false | 0 | '' | null | undefined>;// [0]

Answer:

type Filter<T extends any[], P, U extends unknown[] = []> = 
T extends [infer F,...infer R] 
? F extends P ? Filter<R,P,[...U,F]> : Filter<R,P,U>
: U
type Filter<T extends any[], P,> = 
T extends [infer F,...infer R] 
? F extends P ? [F,...Filter<R,P>] : [...Filter<R,P>]
: []