深入浅出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 服务器。