深入浅出TypeScript | 青训营笔记

21 阅读3分钟

深入浅出TypeScript

TypeScript是一种强类型的 JavaScript 超集,它通过添加静态类型的支持、类、接口、命名空间等特性来扩展 JavaScript 的功能。TypeScript 由 Microsoft 发布,已成为 Web 开发的主流选择之一。

一、TS 基础

1. 类型系统

TypeScript 引入了类型系统,类型检查能力大大提高了代码的可靠性和可读性。在 TypeScript 中,可以使用 :type 来指定变量、函数、类等的类型,例如:

let num: number = 1;
function add(x: number, y: number): number {
  return x + y;
}
class Person {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

还可以使用 any 类型来表示任意类型,例如:

let anything: any = 1;
anything = 'hello';
anything = false;

使用 any 类型的变量,可以随意赋值任意类型的值,但这也导致了 TypeScript 的类型检查功能无法生效,因此在实际应用中应尽量避免使用 any 类型。

2. 接口和类

TypeScript 支持接口和类,它们能够提高代码的可维护性和可读性。接口定义了一个对象的属性和方法,例如:

interface Person {
  name: string;
  age: number;
  sayHi(): void;
}

类则是定义了一个对象的属性和方法的模板,可以继承和实现接口,例如:

class Student extends Person {
  grade: number;
  constructor(name: string, age: number, grade: number) {
    super(name, age);
    this.grade = grade;
  }
  sayHi() {
    console.log(`Hi, I'm ${this.name} and I'm a student.`);
  }
}

3. 函数

函数也是 TypeScript 中的重要部分,可以通过 => 来定义函数的类型,例如:

// 传入两个 number 类型参数,返回 number 类型结果
let add: (a: number, b: number) => number = function (a: number, b: number): number {
  return a + b;
}

此外,TypeScript 还支持默认参数、可选参数、剩余参数和函数重载等特性,例如:

function greet(name: string, message: string = 'Hello') {
  console.log(`${message}, ${name}`);
}

function divide(a: number, b?: number): number {
  if (b === undefined) {
    return a;
  } else {
    return a / b;
  }
}

function sum(...nums: number[]): number {
  return nums.reduce((acc, val) => acc + val, 0);
}

function pick<T, K extends keyof T>(object: T, ...keys: K[]): Pick<T, K> {
  let result = {} as Pick<T, K>;
  keys.forEach(key => result[key] = object[key]);
  return result;
}

function getLength(str: string): number;
function getLength(arr: any[]): number;
function getLength(x: any): number {
  return x.length;
}

4. 类型推断

TypeScript 还有一个重要特性就是类型推断,它能够推断变量的类型,减少了手动指定类型的工作量和代码冗余。例如:

let num = 1; // 推断类型为 number
let arr = [1, 2, 3]; // 推断类型为 number[]
let obj = {name: 'Alice', age: 18}; // 推断类型为 { name: string, age: number }

在需要手动指定类型的情况下,可以使用 as 或 <type> 来进行类型转换:

let num = '1' as number;

二、TS 进阶

1. 泛型

泛型是 TypeScript 中的高级特性,它能够增强代码重用性和灵活性。使用 <> 来定义泛型,例如:

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

let num = identity<number>(1); // 数字类型
let str = identity<string>('hello'); // 字符串类型

还可以使用泛型约束来限制泛型的类型,例如:

interface Lengthwise {
  length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
  console.log(`Length is ${arg.length}`);
  return arg;
}

2. 声明文件

在使用第三方库或框架时,需要使用到它们提供的声明文件来描述库的 API,以便 TypeScript 能够正确地进行类型检查和编译。声明文件通常以 .d.ts 后缀名结尾,可以手动编写,也可以使用第三方工具进行自动生成。例如:

// decarations.d.ts
declare module 'my-library' {
  export function log(message: string): void;
  export function multiply(x: number, y: number): number;
}

在编写代码时,只需通过 import 或 require 来导入对应的库即可:

import { log, multiply } from 'my-library';

log('hello');
const result = multiply(2, 3);

3. 枚举类型

枚举类型是 TypeScript 提供的另一种高级特性,它能够让代码更加可读和可维护。可以使用 enum 来定义枚举类型,例如:

enum Color {
  Red = 1,
  Green = 2,
  Blue = 3,
}

let color: Color = Color.Red; // 枚举类型
let colorName: string = Color[2]; // 枚举字段名

三、TS 实战

1. React & TypeScript

React 和 TypeScript 是很配的一对,一些常见的应用场景包括:

  • 静态类型检查:使用 TypeScript 能够在编译时检测出潜在的类型错误,避免在运行时出现错误。
  • prop 类型检查:定义组件的 prop 类型能够大幅降低由于组件使用错误导致的错误。
  • 类型定义的自动化:使用 TypeDoc 能够将 React 组件的类型定义自动化生成。

以下是一个使用 TypeScript 编写的 React 组件示例:

import React, { FC } from 'react';

// 定义 props 类型
interface Props {
  title: string;
  items: { text: string, completed: boolean }[];
  onToggle: (index: number) => void;
  onRemove: (index: number) => void;
}

const TodoList: FC<Props> = ({ title, items, onToggle, onRemove }) => {
  return (
    <div>
      <h2>{title}</h2>
      <ul>
        {items.map((item, index) => (
          <li key={index}>
            <input type="checkbox" checked={item.completed} onChange={() => onToggle(index)} />
            {item.text}
            <button onClick={() => onRemove(index)}>X</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

2. Node.js & TypeScript

Node.js 也是 TypeScript 的一个很好的应用场景,利用 TypeScript 能够增强 Node.js 的代码健壮性和可读性。以下是一个使用 TypeScript 编写的 Node.js 应用示例:

import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.send('Hello, world!');
});

app.listen(3000, () => {
  console.log('Server started at http://localhost:3000');
});

以上代码使用了 express 框架,并通过 TypeScript 的类型推断和类型定义,实现了一个简单的 HTTP 服务器。