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

TypeScript

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

RequiredByKeys全部属性非只读 Mutable属性排除 OmitByType

ObjectEntriesShiftTuple to Nested Object


中等挑战

一、RequiredByKeys

实现一个通用的RequiredByKeys<T, K>,它接收两个类型参数TK

K指定应设为必选的T的属性集。当没有提供K时,它就和普通的Required<T>一样使所有的属性成为必选的。

type RequiredByPs<T, K extends keyof T = keyof T, O = Omit<T, K> & { [P in K]-?: T[P] }> = { [P in keyof O]: O[P] };
type Merge<T> = {
    [K in keyof T]: T[K];
};
type RequiredByKeys<T, K extends PropertyKey = keyof T> = Merge<T & Required<Pick<T, K extends keyof T ? K : never>>>;
TypeScript提供的工具类型:

Omit<Type, Keys>用来从对象类型Type中,删除指定的属性Keys,组成一个新的对象类型返回。

Required<Type>返回一个新类型,将参数类型Type的所有属性变为必选属性。它与Partial<Type>的作用正好相反。

二、全部属性非只读 Mutable

实现一个通用的类型 Mutable<T>,使类型 T 的全部属性可变(非只读)。
type Mutable<T extends object> = {
    -readonly [K in keyof T]: T[K];
};
type Mutable<T extends object> = {
    -readonly [K in keyof T]: T[K] extends Record<string, unknown> ? Mutable<T[K]> : T[K];
};

三、属性排除 OmitByType

From T, pick a set of properties whose type are not assignable to U.
// For Example
type OmitBoolean = OmitByType<
    {
        name: string;
        count: number;
        isReadonly: boolean;
        isEnable: boolean;
    },
    boolean
>; // { name: string; count: number }
type OmitByType<T, U> = {
    [K in keyof T as T[K] extends U ? never : K]: T[K];
};

四、ObjectEntries

Implement the type version of Object.entries
// For example
interface Model {
    name: string;
    age: number;
    locations: string[] | null;
}
type modelEntries = ObjectEntries<Model>; // ['name', string] | ['age', number] | ['locations', string[] | null];
type ObjectEntries<T, U = Required<T>> = {
    [K in keyof U]: [K, U[K] extends never ? undefined : U[K]];
}[keyof U];
TypeScript提供的工具类型:

Required<Type>返回一个新类型,将参数类型Type的所有属性变为必选属性。它与Partial<Type>的作用正好相反。

五、Shift

Implement the type version of Array.shift

For example: ` type Result = Shift<[3, 2, 1]> // [2, 1]`

type Shift<T extends unknown[]> = T extends [infer _, ...infer U] ? [...U] : T;

六、Tuple to Nested Object

Given a tuple type T that only contains string type, and a type U, build an object recursively.

For example:

type a = TupleToNestedObject<["a"], string>; // {a: string}
type b = TupleToNestedObject<["a", "b"], number>; // {a: {b: number}}
type c = TupleToNestedObject<[], boolean>; // boolean. if the tuple is empty, just return the U type
type TupleToNestedObject<T, U> = T extends [infer F, ...infer R] ? { [K in F & string]: TupleToNestedObject<R, U> } : U;
type TupleToNestedObject<T, U> = T extends [infer F extends PropertyKey, ...infer R] ? { [K in F]: TupleToNestedObject<R, U> } : U;
type TupleToNestedObject<T, U> = T extends [infer F extends PropertyKey, ...infer R] ? Record<F, TupleToNestedObject<R, U>> : U;

type PropertyKey = string | number | symbol; type Record<T extends keyof any, U> = { [K in T]: U; };