🎉 TypeScript 的超能力:工具类型、泛型、类型推断和类型断言的幽默指南 🎉

TypeScript 是一种静态类型的超集语言,它在 JavaScript 的基础上增加了类型系统,以提高代码的可读性和可维护性。在 TypeScript 中,工具类型(Utility Types)、泛型(Generics)、类型推断(Type Inference)以及类型断言(Type Assertions)是四个非常重要的概念,它们允许开发者以更灵活和强大的方式来处理类型。

工具类型(Utility Types)

工具类型是 TypeScript 提供的一系列预定义的类型,用于在编译时对类型进行操作和转换。

常用工具类型

Partial

将 T 类型中的所有属性变为可选。

interface Todo {
  title: string;
  completed: boolean;
}

// 使用 Partial 工具类型
const todo: Partial = { title: ‘Write TypeScript’ };
// ‘completed’ 属性是可选的

Readonly

使 T 类型中的所有属性变为只读。

const todo: Readonly = { title: 'Write TypeScript', completed: true };
// 'todo' 对象的属性不能被重新赋值

Record

构造一个类型,其键的类型为 K,值的类型为 V。

// 使用 Record 工具类型
const map: Record = { key: 'value' };

Pick

从 T 类型中挑选出 K 类型的属性,创建一个新的类型。

type TodoPreview = Pick;
const preview: TodoPreview = { title: 'Write TypeScript' };
// 'completed' 属性被排除在外

Omit

从 T 类型中排除 K 类型的属性,创建一个新的类型。

type TodoWithoutCompleted = Omit;
const todoWithoutCompleted: TodoWithoutCompleted = { title: 'Write TypeScript' };
// 'completed' 属性被排除在外

泛型(Generics)

泛型允许开发者定义函数、接口或类时,不预先指定具体的类型,而是使用类型参数(Type Parameters)来表示这些类型。

泛型的基本使用

定义泛型函数

function identity(arg: T): T {
  return arg;
}

// 使用类型推断,不需要显式指定 T
const output = identity(“Hello World”);

定义泛型接口

interface GenericIdentityFn {
  (arg: T): T;
}

// 使用类型推断,实现接口时不需要显式指定 T
function identityFn(arg: number): number {
return arg;
}

const myIdentity: GenericIdentityFn = identityFn;

定义泛型类

class GenericNumber {
  zeroValue: T;
  add: (x: T, y: T) => T;
}

// 使用类型推断,创建实例时不需要显式指定 T
let myGenericNumber = new GenericNumber();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = (x, y) => x + y;

泛型约束(Generic Constraints)

泛型约束允许我们指定类型参数必须满足的接口或类型。

interface Lengthwise {
  length: number;
}

function loggingIdentity(arg: T): T {
console.log(arg.length);
return arg;
}

// 使用类型推断,调用时不需要显式指定 T
const stringLength = loggingIdentity(“Hello TypeScript”);

类型推断(Type Inference)

类型推断是 TypeScript 编译器根据已有的上下文信息自动确定变量类型的能力。

类型推断的使用

变量声明

const myNumber = 10;
// TypeScript 推断 myNumber 的类型为 number

函数参数

function add(x, y) {
  return x + y;
}

const result = add(1, 2);
// TypeScript 推断 add 函数的参数类型为 number

函数返回值

function createArray(...elements: T[]): T[] {
  return elements;
}

const strings = createArray(“Hello”, “TypeScript”);
// TypeScript 推断 createArray 函数返回一个 string 数组

类型断言(Type Assertions)

类型断言是一种告诉 TypeScript 编译器“相信我,我比你更清楚这个类型是什么”的方式。它允许开发者覆盖编译器的类型推断,显式指定一个类型的值。

类型断言的使用

基本类型断言

const myValue = "this is a string";
const myNumber = myValue as number;
// 断言 myValue 为 number 类型,尽管实际上它不是

类型断言在泛型中的使用

function getFirstItem(array: T[]): T {
  return array[0];
}

const myItems = [1, 2, 3];
const firstItem = getFirstItem(myItems);

// 使用类型断言,明确 firstItem 的类型
const firstString: string = firstItem as string;

使用场景

类型断言、工具类型、泛型和类型推断的结合使用场景非常广泛,它们可以用于:

  1. 创建可重用的代码。
  2. 提供类型安全的函数和类。
  3. 定义灵活的数据结构。
  4. 增强代码的可读性和可维护性。

例如,在实现一个缓存系统时,可以使用泛型和类型推断来允许缓存任何类型的数据,同时使用类型断言来确保类型安全:

class Cache {
  private data: Map = new Map();

set(key: string, value: T): void {
this.data.set(key, value);
}

get(key: string): T | undefined {
return this.data.get(key);
}
}

// 使用类型推断创建一个特定类型的缓存实例
const stringCache = new Cache();
stringCache.set(“key1”, “value1”);

// 使用类型断言确保类型安全
const cachedValue = stringCache.get(“key1”)!;
</string,>

在这个例子中,cachedValue 使用了非空断言(!),这告诉 TypeScript 编译器 get 方法将返回一个 string 类型,而不是 string | undefined

总结来说,TypeScript 的工具类型、泛型、类型推断和类型断言是构建类型安全和灵活代码的强大工具。通过合理使用它们,可以大幅提升代码的质量和开发效率。


这是一个从 https://juejin.cn/post/7368836713965469735 下的原始话题分离的讨论话题