這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前期準備
本篇文章的撰寫目的是為了提升TS型別的書寫質量,高質量的型別可以提高專案的可維護性并避免一些潛在的漏洞;
在學習本篇之前需要有一定的TS基礎知識,在此基礎上可以更好的完成各種型別的挑戰,撰寫出屬于自己的型別工具;
這里推薦我之前梳理的基礎知識點 一份夠用的TS常用特性總結 或 TS中文檔案 ;
目前只完成了easy型別和部分medium型別的訓練,后續會持續補充;
easy
readonly
實作Readonly,接收一個泛型引數,并回傳一個完全一樣的型別,只是所有屬性都會被readonly所修飾,
type MyReadonly<T> = {
readonly [P in keyof T] : T[P]
}
interface Todo {
title: string;
description: string;
}
const todoObj: MyReadonly<Todo> = {
title: "Hey",
description: "foobar",
};
console.log(todoObj.title)
todoObj.description = "barFoo"; // Error: cannot reassign a readonly property
first-of-array
實作First,他接受一個陣列 T 并回傳它的第一個元素型別
type First<T extends any[]> = T extends [] ? never : T[0]; type arr1 = ['a', 'b', 'c'] type arr2 = [3, 2, 1] type head1 = First<arr1> // expected to be 'a' type head2 = First<arr2> // expected to be 3
tuple-to-object
實作TupleToObject,傳入元組型別,將元組型別轉換為物件型別,這個物件型別的鍵/值都是從元組中遍歷出來,
type TupleToObject<T extends readonly any[]> = {
[P in T[number]]: P;
};
const tuple = ["tesla", "model 3", "model X", "model Y"] as const;
type result = TupleToObject<typeof tuple>; // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}
length of tuple
創建一個通用的Length,接受一個readonly的陣列,回傳這個陣列的長度,
type Length<T extends readonly unknown[]> = T["length"]; type tesla = ["tesla", "model 3", "model X", "model Y"]; type spaceX = [ "FALCON 9", "FALCON HEAVY", "DRAGON", "STARSHIP", "HUMAN SPACEFLIGHT" ]; type teslaLength = Length<tesla>; // expected 4 type spaceXLength = Length<spaceX>; // expected 5
Exclude
從聯合型別T中排除U的型別成員,來構造一個新的型別,
type MyExclude<T, U> = T extends U ? never : T; type Result = MyExclude<"a" | "b" | "c", "a">; // 'b' | 'c'
Awaited
假如我們有一個 Promise 物件,這個 Promise 物件會回傳一個型別,在 TS 中,我們用 Promise 中的 T 來描述這個 Promise 回傳的型別,請你實作一個型別,可以獲取這個型別, 例如:Promise,請你回傳 ExampleType 型別,
type MyAwaited<T> = T extends PromiseLike<infer R> ? MyAwaited<R> : T type ExampleType = Promise<string> type Results = MyAwaited<ExampleType> // string
IF
實作一個 IF 型別,它接收一個條件型別 C ,一個判斷為真時的回傳型別 T ,以及一個判斷為假時的回傳型別 F, C 只能是 true 或者 false, T 和 F 可以是任意型別,
type If<C extends boolean, T, F> = C extends true ? T : F; type A = If<true, "a", "b">; // expected to be 'a' type B = If<false, "a", "b">; // expected to be 'b'
Concat
在型別系統里實作 JavaScript 內置的 Array.concat 方法,這個型別接受兩個引數,回傳的新陣列型別應該按照輸入引數從左到右的順序合并為一個新的陣列,
type Concat<T extends any[], U extends any[]> = [...T, ...U]; type ResultConcat = Concat<[1], [2]>; // expected to be [1, 2]
Include
實作 Array.includes 方法,這個型別接受兩個引數,回傳的型別要么是 true 要么是 false,
type Includes<T extends readonly any[], U> = U extends T[number] ? true : false type isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Esidisi'> // expected to be `false`
Push
實作通用的Array.push型別,
type Push<T extends readonly unknown[], U> = [...T, U]; type Resulted = Push<[1, 2], "3">; // [1, 2, '3']
Unshift
實作型別 Array.unshift型別,
type Unshift<T extends readonly unknown[], U> = [U, ...T]; type UnshiftList = Unshift<[1, 2], 0>; // [0, 1, 2,]
Parameters
實作內置的 Parameters 型別,
type MyParameters<T extends (...args: any[]) => any> = T extends (
...args: infer U
) => any
? U
: never;
const foo = (arg1: string, arg2: number): void => {};
type FunctionParamsType = MyParameters<typeof foo>; // [arg1: string, arg2: number]
edium
ReturnType
不使用 ReturnType 實作 TypeScript 的 ReturnType 泛型,
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
const fn = (v: boolean) => {
if (v) return 1;
else return 2;
};
type a = MyReturnType<typeof fn>; // 應推匯出 "1 | 2"
Omit
不使用 Omit 實作 TypeScript 的 Omit<T, K> 泛型,Omit 會創建一個省略 K 中欄位的 T 物件,
type MyOmit<T, K extends keyof any> = {
[key in Exclude<keyof T, K>]: T[key];
};
interface Todo {
title: string;
description: string;
completed: boolean;
}
type TodoPreview = MyOmit<Todo, "description" | "title">;
const todo: TodoPreview = {
completed: false,
};
ReadOnly2
實作一個通用MyReadonly2<T, K>,它帶有兩種型別的引數T和K, K指定應設定為Readonly的T的屬性集,如果未提供K,則應使所有屬性都變為只讀,就像普通的Readonly一樣,
type MyReadonly2<T, K extends keyof T = keyof T> = {
readonly [P in K]: T[P];
} & {
[P in Exclude<keyof T, K>]: T[P];
};
interface Todo {
title: string;
description: string;
completed: boolean;
}
const todos: MyReadonly2<Todo, "title" | "description"> = {
title: "Hey",
description: "foobar",
completed: false,
};
todos.title = "Hello"; // Error: cannot reassign a readonly property
todos.description = "barFoo"; // Error: cannot reassign a readonly property
todos.completed = true; // OK
DeepReadonly
實作一個通用的DeepReadonly,它將物件的每個引數及其子物件遞回地設為只讀,
type DeepReadonly<T> = T extends Function
? T
: {
readonly [K in keyof T]: K extends Object ? DeepReadonly<T[K]> : T[K];
};
type X = {
x: {
a: 1;
b: "hi";
};
y: "hey";
};
type Expected = {
readonly x: {
readonly a: 1;
readonly b: "hi";
};
readonly y: "hey";
};
type Todo = DeepReadonly<X>; // should be same as `Expected`
TupleToUnion
實作泛型TupleToUnion,它回傳元組所有值的合集,
type TupleToUnion<T extends unknown[]> = T[number] type Arr = ['1', '2', '3'] type Test = TupleToUnion<Arr> // expected to be '1' | '2' | '3'
LastOfArray
實作一個Last,它接受一個陣列T并回傳其最后一個元素的型別,
type Last<T extends unknown[]> = T extends [...unknown[], infer R] ? R : never type arr1 = ['a', 'b', 'c'] type arr2 = [3, 2, 1] type tail1 = Last<arr1> // expected to be 'c' type tail2 = Last<arr2> // expected to be 1
https://juejin.cn/post/7193917621069152311
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/544139.html
標籤:其他
上一篇:react 高效高質量搭建后臺系統 系列 —— 前端權限
下一篇:幾行代碼給網站添加暗黑模式

