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 21, 2024     Ganace     Front-end-Foundation

TypeScript

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

AnyOfIsNeverIsUnion

ReplaceKeysRemove Index SignaturePercentage Parser


中等挑战

一、AnyOf

类型系统中实现类似于 Pythonany 函数。类型接收一个数组,如果数组中任一个元素为真,则返回 true,否则返回 false。如果数组为空,返回 false
type Falsy = 0 | "" | false | [] | { [key: string]: never } | undefined | null;
type AnyOf<T extends readonly any[]> = T[number] extends Falsy ? false : true;

二、IsNever

Implement a type IsNever, which takes input type T. If the type of resolves to never, return true, otherwise false.
//  For example:
type A = IsNever<never>; // expected to be true
type B = IsNever<undefined>; // expected to be false
type C = IsNever<null>; // expected to be false
type D = IsNever<[]>; // expected to be false
type E = IsNever<number>; // expected to be false
type IsNever<T> = [T] extends [never] ? true : false;
// or
type IsNever<T> = T[] extends never[] ? true : false;

三、IsUnion

Implement a type IsUnion, which takes an input type T and returns whether T resolves to a union type.
// For example:
type case1 = IsUnion<string>; // false
type case2 = IsUnion<string | number>; // true
type case3 = IsUnion<[string | number]>; // false
type IsUnion<T, C = T> = [T] extends [never] ? false : T extends C ? ([C] extends [T] ? false : true) : false;
// 同
type IsUnion<T, C = T> = [T] extends [never] ? false : T extends T ? ([C] extends [T] ? false : true) : false;

四、ReplaceKeys

Implement a type ReplaceKeys, that replace keys in union types, if some type has not this key, just skip replacing, A type takes three arguments.
// For example:
type NodeA = {
    type: "A";
    name: string;
    flag: number;
};

type NodeB = {
    type: "B";
    id: number;
    flag: number;
};

type NodeC = {
    type: "C";
    name: string;
    flag: number;
};

type Nodes = NodeA | NodeB | NodeC;

type ReplacedNodes = ReplaceKeys<Nodes, "name" | "flag", { name: number; flag: string }>; // {type: 'A', name: number, flag: string} | {type: 'B', id: number, flag: string} | {type: 'C', name: number, flag: string} // would replace name from string to number, replace flag from number to string.

type ReplacedNotExistKeys = ReplaceKeys<Nodes, "name", { aa: number }>; // {type: 'A', name: never, flag: number} | NodeB | {type: 'C', name: never, flag: number} // would replace name to never
type ReplaceKeys<U, T, Y> = {
    [K in keyof U]: K extends T ? (K extends keyof Y ? Y[K] : never) : U[K];
};

五、Remove Index Signature

Implement RemoveIndexSignature<T> , exclude the index signature from object types.
// For example:
type Foo = {
    [key: string]: any;
    foo(): void;
};

type A = RemoveIndexSignature<Foo>; // expected { foo(): void }
type RemoveIndexSignature<T, P = PropertyKey> = {
    [K in keyof T as P extends K ? never : K extends P ? K : never]: T[K];
};

六、Percentage Parser

实现类型 PercentageParser。根据规则 /^(+|-)?(\d*)?(\%)?$/ 匹配类型 T。

匹配的结果由三部分组成,分别是:[正负号, 数字, 单位],如果没有匹配,则默认是空字符串。

type CheckPrefix<T> = T extends "+" | "-" ? T : never;
type CheckSuffix<T> = T extends `${infer P}%` ? [P, "%"] : [T, ""];
type PercentageParser<A extends string> = A extends `${CheckPrefix<infer L>}${infer R}` ? [L, ...CheckSuffix<R>] : ["", ...CheckSuffix<A>];
type PercentageParser<A extends string> = A extends `${infer L}${infer R}`
    ? L extends "+" | "-"
        ? R extends `${infer N}%`
            ? [L, N, "%"]
            : [L, R, ""]
        : A extends `${infer N}%`
        ? ["", N, "%"]
        : ["", A, ""]
    : ["", "", ""];