likes
comments
collection
share

TypeScript实用技巧大杂烩,助你成为真正的全栈工程师

作者站长头像
站长
· 阅读数 15

作为一个全栈工程师,精通一门语言是远远不够的。在 JavaScript 方式盛行的当下,TypeScript 更是成为了众多前端开发的选择。TypeScript 不仅有更好的开发体验,还能提高代码的健壮性,减少错误和编码时间。在本文中,我们将介绍 TypeScript 中一些实用技巧,助你成为真正的全栈工程师!

一、声明文件的使用技巧

声明文件的引入方式

声明文件可以让 TypeScript 对库、框架等第三方代码进行类型检查,提供更好的开发体验和代码可读性。当我们使用其他开源类库时,需要在项目中引入其对应的声明文件。 推荐使用 npm 安装库时自动下载声明文件的方式,例如我们在使用 lodash 库的时候,在命令行中输入:

npm install lodash --save-dev
npm install @types/lodash --save-dev

使用 namespace 保持代码干净整洁

当我们使用多个第三方库时,可能存在名称冲突的问题。这时可以使用 namespace 来避免冲突:

namespace MyUtils {
  export function toArray<T>(args: IArguments): T[] {
    return Array.prototype.slice.call(args);
  }
}

namespace MyUtils2 {
  export function toArray<T>(args: Array<T>): T[] {
    return Array.from(args);
  }
}

// 调用 toArray 方法
const arr1 = MyUtils.toArray(arguments);
const arr2 = MyUtils2.toArray([1, 2, 3]);

二、使用装饰器提升代码的可读性和可维护性

类的装饰器

装饰器是一种特殊的声明,它可以被附加到类声明、方法、属性或参数上,以修改类的行为。常见的类装饰器有:

// 简单的类装饰器
function myClassDecorator(target: any) {
  // 修改类的行为、增加方法等
}

// 携带参数的类装饰器
function myClassDecoratorFactory(name: string) {
  return function (target: any) {
    // 修改类的行为、增加方法等
  };
}

@myClassDecorator
class MyClass {}

@myClassDecoratorFactory('foo')
class MyClass2 {}

属性的装饰器

属性装饰器是指修饰类中声明的属性,用于在类中添加元数据、修改属性的行为。常见的属性装饰器有:

function myPropDecorator(target: any, key: string) {
  // 修改属性的行为,添加元数据等
}

class MyClass {
  // 使用属性装饰器
  @myPropDecorator
  myProp: number;
}

方法的装饰器

方法装饰器是指修饰类中声明的方法,用于在方法中添加元数据、修改方法行为。常见的方法装饰器有:

function myMethodDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
  // 修改方法的行为,添加元数据等
}

class MyClass {
  // 使用方法装饰器
  @myMethodDecorator
  myMethod() {}
}

三、泛型编程的技巧

理解泛型中的类型约束

泛型能帮助我们在编写代码时写出更加通用的逻辑。但是泛型也存在着一些坑,例如类型约束的问题。当我们定义一个泛型函数时,需要确保输入参数类型的兼容性:

function fn<T extends { length: number }>(arg: T): T {
  console.log(arg.length);
  return arg;
}

fn(1); // Error,number 没有 length 属性
fn('hello'); // OK,string 有 length 属性

使用泛型编写可复用的代码

泛型还可以帮助我们编写更加通用的代码,提高代码的可复用性。例如常见的数组去重操作:

function unique<T>(arr: T[]): T[] {
  return Array.from(new Set(arr));
}

const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = unique(arr); // [1, 2, 3, 4, 5]

四、类型推导技巧

使用 never 类型提高代码健壮性

TypeScript 中有一个 never 类型,它表示的是那些永远不会出现的值的类型。在代码中,我们可以利用 never 类型来确保代码的健壮性。例如:

function throwError(msg: string): never {
  throw new Error(msg);
}

function isNotNull<T>(val: T): val is NonNullable<T> {
  if (val === null || val === undefined) {
    throwError('value is null or undefined');
  }
  return true;
}

const str: string | null = null;
if (isNotNull(str)) {
  // str 不可能是 null,这里会推导出类型为 string
  console.log(str.length);
}

使用 keyof 获取对象属性名称

keyof 是 TypeScript 中的一种关键字,它可以获取某个对象属性的名称:

interface Person {
  name: string;
  age: number;
}

type PersonKey = keyof Person; // 'name' | 'age'

自定义索引类型,规范对象结构

在开发中,我们可能需要自定义一些索引类型来规范对象的结构:

interface Person {
  name: string;
  age: number;
}

type PartialPerson = Partial<Person>; // 把 Person 所有属性变成可选属性
type RequiredPerson = Required<Person>; // 把 Person 所有属性变成必选属性
type OmitPerson = Omit<Person, 'age'>; // 从 Person 中删除 age 属性

五、常用工具类型解析

Partial 类型,将类型属性变成可选的

Partial 是 TypeScript 中的一个工具类型,它可以把一个类型中所有属性变成可选的:

interface Person {
  name: string;
  age: number;
}

type PartialPerson = Partial<Person>; // 把 Person 所有属性变成可选属性

Required类型,将类型属性变成必选的

Partial 相反,Required 可以把一个类型中所有属性变成必选的:

interface Person {
  name?: string;
  age?: number;
}

type RequiredPerson = Required<Person>; // 把 Person 所有属性变成必选属性

Omit 类型,从类型中删除某个属性

Omit 可以从一个类型中删除指定的属性:

interface Person {
  name: string;
  age: number;
  gender: string;
}

type WithoutGender = Omit<Person, 'gender'>; // 从 Person 中删除 gender 属性

六、高效应对循环和异步场景

使用 async/await 优雅处理异步操作

在处理异步操作时,我们通常会使用 Promise,而在 TypeScript 中,可以使用 async/await 更加优雅的处理异步操作。例如:

async function fetchUserInfo() {
  const res = await fetch('https://api.com/userinfo');
  const data = await res.json();
  return data;
}

fetchUserInfo().then((userInfo) => {
  console.log(userInfo);
});

数据处理循环的技巧

在数据处理中,我们经常使用循环来遍历数据。而在 TypeScript 中,可以使用 for...of 循环更加简化代码,同时提高代码的可读性和可维护性。例如:

interface Person {
  name: string;
  age: number;
}

const people: Person[] = [
  { name: 'Alice', age: 20 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 30 },
];

for (const { name, age } of people) {
  console.log(name, age);
}

总结

本文介绍了 TypeScript 中一些实用技巧,包括声明文件的使用技巧、使用装饰器提升代码可读性和可维护性、泛型编程技巧、类型推导技巧和常用工具类型解析、高效应对循环和异步场景等。希望这些技巧能帮助你写出更加优秀的 TypeScript 代码,成为真正的全栈工程师!