十个高级开发者需要知道的TypeScript 技巧

开发 前端
TypeScript 已迅速成为像我这样的开发人员的首选语言,他们希望通过添加类型安全、更好的工具和改进的可维护性来改进 JavaScript 代码库。

 TypeScript 已迅速成为像我这样的开发人员的首选语言,他们希望通过添加类型安全、更好的工具和改进的可维护性来改进 JavaScript 代码库。

随着语言的发展和成熟,TypeScript 沿途获得了一些隐藏的功能。 在本文中,我们将深入探讨 10 个鲜为人知的技巧,它们将帮助您释放 TypeScript 的全部潜力。

1. 使用 keyof 和映射类型动态构建类型

keyof 关键字提供了一种基于现有类型的键动态构建类型的强大工具。

“keyof 运算符采用对象类型并生成其键的字符串或数字文字联合。”

— TypeScript 文档

结合映射类型,您可以从现有类型生成新类型,同时保留原始结构。

type Point = { x: number; y: number };


type NullablePoint = {
  [K in keyof Point]: Point[K] | null;
};

在这里,NullablePoint 成为一种新类型,具有与 Point 相同的键,但具有可为空的值。

2. 灵活类型的条件类型

条件类型允许创建依赖于其他类型的复杂类型。 这可以导致更灵活和可重用的类型定义。

type Flatten<T> = T extends Array<infer U> ? U : T;


type FlattenedNumbers = Flatten<number[]>; // number

在此示例中,Flatten 类型检查提供的类型 T 是否为数组,如果是,则提取内部类型 U。

3. 类型柯里化的部分应用类型

TypeScript 对高阶类型的支持允许您创建部分应用的类型。 这种称为类型套用的技术可实现强大的组合模式。

type Curried<T, U> = (arg: U) => T & U;


function merge<T, U>(fn: Curried<T, U>): T & U {
  return fn({} as U);
}


type UserDetails = { firstName: string; lastName: string };
type UserSettings = { theme: string; language: string };


const result = merge<UserDetails, UserSettings>(() => ({
  firstName: 'John',
  lastName: 'Doe',
  theme: 'dark',
  language: 'en',
}));


console.log(result);
/** {
  "firstName": "John",
  "lastName": "Doe",
  "theme": "dark",
  "language": "en"
} */

在此示例中,我们有两种不同类型的对象,UserDetails 和 UserSettings。 通过使用 merge 函数,我们可以将这两种类型组合成一个包含两种类型属性的对象。 当您想要创建一个新对象来组合来自多个来源的属性,同时仍保持 TypeScript 类型完整时,这会很有用。

当然,在 TypeScript 中还有其他方法可以实现这一点,例如,使用类型交集和直接扩展语法。 此示例的主要目的是演示类型柯里化的概念,当在正确的上下文中应用时,它可以成为一种强大的技术。

4. 编译时类型检查的类型保护

当您需要执行编译时类型检查时,类型保护很有用。 它们允许 TypeScript 缩小特定代码块中值的类型。

function isString(value: any): value is string {
  return typeof value === "string";
}


function concat(a: unknown, b: unknown) {
  if (isString(a) && isString(b)) {
    return a.concat(b);
  }
}

在 concat 函数中,TypeScript 知道 a 和 b 是字符串,因为类型保护是 isString。 这也可以改进 VS Code Intellisense 的提示,因为编译器将能够约束任何类型。

5. 带返回类型的高级类型推断

Return Type 实用程序类型可以推断函数的返回类型,从而更容易使用高阶函数及其类型。

type MyFunction = (x: number, y: number) => { result: number };


type MyFunctionReturnType = ReturnType<MyFunction>; // { result: number }

在这里,MyFunctionReturnType 成为 MyFunction 的推断返回类型。

6. 递归类型的类型级编程

TypeScript 支持递归类型,允许您创建复杂的类型级计算和转换。

type TupleToUnion<T extends any[]> = T[number];


type MyTuple = [string, number, boolean];


type MyUnion = TupleToUnion<MyTuple>; // string | number | boolean

在此示例中,TupleToUnion 将元组类型转换为联合类型,这在处理复杂数据结构时非常有用。

就个人而言,我更喜欢联合类型而不是枚举,以至于我会将我看到的任何枚举重构为联合类型。 智能感知更好!

7. 不可变类型只读

TypeScript 提供了一个内置的 Readonly 实用程序类型,它使对象的所有属性都成为只读的。 当您想在代码库中强制执行不变性时,这很有用。

type User = { name: string; age: number };
type ReadonlyUser = Readonly<User>;


const user: ReadonlyUser = { name: "Alice", age: 30 };


user.age = 31;
// Error: Cannot assign to 'age' because it is a read-only property

通过使用 Readonly 实用程序,我们确保用户对象不会发生变化。

8. 类型断言以获得更多控制

当您对值的类型的了解比 TypeScript 的类型推断所能推断的更多时,类型断言很有用。 它们允许您为值指定更精确的类型,而无需执行任何运行时检查。

const unknownValue: unknown = "hello world";


const stringValue: string = unknownValue as string;

在此示例中,我们断言 unknownValue 确实是一个字符串,TypeScript 将信任此断言。

9. 更安全常量的唯一符号

TypeScript 独特的符号类型可以创建独特的非字符串值,非常适合更安全的常量定义和避免名称冲突。

const MyConstant = Symbol("MyConstant") as unique symbol;


type MyType = {
  [MyConstant]: string;
};


const obj: MyType = { [MyConstant]: "hello world" };


console.log(obj[MyConstant]); // "hello world"

在这里,MyConstant 是一个独特的符号,确保没有其他属性可以与它冲突。

10.代码组织的合并类型声明

TypeScript 允许合并类型声明,这在跨多个文件拆分类型定义或从外部库扩展类型时非常有用。

// file1.ts
interface Point {
  x: number;
  y: number;
}


// file2.ts
interface Point {
  z: number;
}


// Merged Point type: { x: number; y: number; z: number }

通过在 file1.ts 和 file2.ts 中声明 Point,TypeScript 会将两个声明合并为一个类型。 我认为这种行为只发生在 interface 关键字上,而不是 type 关键字,所以我更喜欢 type。

这 10 个 TypeScript 提示和技巧应该可以帮助您提升 TypeScript 技能并编写更强大、灵活和可维护的代码。

不要害怕探索 TypeScript 的高级功能,并在您的项目中利用它们来实现更干净、更安全的代码。


责任编辑:华轩 来源: web前端开发
相关推荐

2022-11-07 16:06:15

TypeScript开发技巧

2022-04-26 18:33:02

JavaScript技巧代码

2016-02-22 15:09:19

Android项目管理技巧

2022-10-20 15:12:43

JavaScript技巧开发

2023-03-31 08:10:50

2013-06-28 14:19:20

2021-12-24 11:24:59

React HackReact JavaScript

2022-08-10 09:03:35

TypeScript前端

2021-12-08 23:38:25

Python工具代码

2010-07-30 16:27:06

Flex开发

2014-09-29 10:08:34

2015-09-20 16:23:27

2011-05-26 11:13:36

Flex

2014-07-17 09:31:50

iOS8SDK

2010-03-01 10:20:27

Flex

2015-08-21 09:47:02

ios9sdk新特性

2017-06-09 13:33:57

2011-12-05 22:44:53

Android

2018-09-29 15:27:05

BinderAPPAndroid

2023-12-23 11:15:25

点赞
收藏

51CTO技术栈公众号