Extract 工具类型八个使用技巧

2024年 3月 21日 84.8k 0

Extract 是 TypeScript 中内置的工具类型,它用于从联合类型中提取出符合某个条件的类型,生成一个新的类型。这个工具类型在日常开发中非常有用,它能够帮助我们编写类型安全的代码和更好地实现代码复用。

/**
 * Extract from T those types that are assignable to U.
 * typescript/lib/lib.es5.d.ts
 */
type Extract = T extends U ? T : never;

type T0 = Extract
// type T0 = "a"

本文我将介绍 Extract 工具类型的 8 个使用技巧,掌握这些技巧之后,在工作中你就能更好地利用 Extract

1.提取指定的基本数据类型

type MyTypes = string | number | boolean;
type StringOrNumber = Extract;

let uid: StringOrNumber = "semlinker" // Ok
uid = 2024 // Ok
uid = false // Error
// Type 'boolean' is not assignable to type 'StringOrNumber'.

2.提取指定的字符串字面量类型

type Color = 'red' | 'green' | 'blue' | 'yellow';
type PrimaryColors = Extract;

const primaryColor: PrimaryColors = 'blue'; // Ok
const secondaryColor: PrimaryColors = 'yellow'; // Error
// Type '"yellow"' is not assignable to type 'PrimaryColors'.

3.提取可调用的函数类型

type Value = string | number | (() => void);
type CallableFn = Extract;

const fn1: CallableFn = () => console.log('semlinker'); // Ok
const fn2: CallableFn = 'semlinker'; // Error
// Type 'string' is not assignable to type '() => void'.

4.提取两个联合类型的共有成员

type TaskStatus = "Todo" | "InProgress" | "Done" | "Archived";
type ModuleHandledStatus = "Todo" | "Done" | "OnHold";

type ModuleSpecificStatus = Extract;
// type ModuleSpecificStatus = "Todo" | "Done"

5.提取含有特定属性的子类型

Animal 联合类型,包含了多种动物的描述对象,我们想从中提取出含有 "legs" 属性的子类型。

type Animal =
    | { type: 'dog', legs: number }
    | { type: 'cat', legs: number }
    | { type: 'fish', fins: number };

type AnimalsWithLegs = Extract;

const dog: AnimalsWithLegs = { type: 'dog', legs: 4 }; // Ok
const cat: AnimalsWithLegs = { type: 'cat', legs: 4 }; // Ok
const fish: AnimalsWithLegs = { type: 'fish', fins: 6 }; // Error
// Type '"fish"' is not assignable to type '"dog" | "cat"'.

6.提取特定的事件类型

type EventTypes = MouseEvent | KeyboardEvent | TouchEvent;

type OnlyMouseEvents = Extract;

function handleMouseEvent(event: OnlyMouseEvents) {
    console.log('Handling mouse event:', event.clientX, event.clientY);
}

document.addEventListener('click', (event) => {
    handleMouseEvent(event); // OK
});

document.addEventListener('keydown', (event) => {
    handleMouseEvent(event); // Error
    // Argument of type 'KeyboardEvent' is not assignable to parameter of type 'MouseEvent'.
});

7.在类型守卫中使用 Extract

使用 Extract 可以在类型守卫中精确地过滤类型,使得在条件分支中可以安全地使用过滤后的类型。

type Pet = { type: 'dog', bark: () => void } | { type: 'cat', meow: () => void };

function isDog(pet: Pet): pet is Extract {
    return pet.type === 'dog';
}

const pet1: Pet = { type: 'dog', bark: () => console.log('Woof!') }
const pet2: Pet = { type: "cat", meow: () => console.log("Meow!") }
console.log(`pet1 is dog: ${isDog(pet1)}`) // "pet1 is dog: true" 
console.log(`pet2 is dog: ${isDog(pet2)}`) // "pet2 is dog: false"

8.在函数重载中使用 Extract

在处理 API 请求的场景中,我们需要根据不同的请求类型(如 GET、POST、DELETE)处理不同类型的数据。为了增强类型安全和确保每种请求类型都正确地处理其数据,我们可以利用 TypeScript 的函数重载和 Extract 工具类型。

type RequestType = 'GET' | 'POST' | 'DELETE';
type RequestData = {
    GET: undefined;
    POST: { body: string };
    DELETE: { resourceId: number };
};

// Function overloading, based on the request type, accepts matching data types
function sendRequest(type: 'GET', data: Extract): void;
function sendRequest(type: 'POST', data: Extract): void;
function sendRequest(type: 'DELETE', data: Extract): void;
function sendRequest(type: T, data: RequestData[T]): void {
    console.log(`Sending ${type} request with data:`, data);
}

sendRequest('GET', undefined); // Ok
sendRequest('POST', { body: "semlinker" }); // Ok
sendRequest('DELETE', { resourceId: 2024 }); // Ok

sendRequest('POST', { body: 2024 }); // Error
// Type 'number' is not assignable to type 'string'.
sendRequest('DELETE', undefined); // Error
// Argument of type 'undefined' is not assignable to parameter of type '{ resourceId: number; }'.

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论