第一部分:基础知识
1. 什么是TypeScript?
TypeScript是JavaScript的超集,主要增加了静态类型和一些面向对象编程的特性。TypeScript的代码最终会被编译为JavaScript,可以在任何支持JavaScript的环境中运行。
TypeScript的特点
- 静态类型:可选的静态类型系统,可以在编译期间发现错误。
- 编译时检查:提供更早的错误检测,减少运行时错误。
- 面向对象:支持类、接口、继承等面向对象的编程范式。
- 模块化:支持ES6模块,使代码结构更清晰。
2. TypeScript的安装
要在项目中使用TypeScript,首先需要安装TypeScript编译器。可以使用npm来安装:
npm install -g typescript
安装完成后,可以使用以下命令验证:
tsc -v
第二部分:TypeScript基础语法
1. 基本类型
TypeScript 支持多种基本数据类型,主要包括:
1.1 数字类型
let num: number = 42;
1.2 字符串类型
let str: string = "Hello TypeScript";
1.3 布尔类型
let isActive: boolean = true;
1.4 数组类型
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];
1.5 元组类型
元组是一种特殊的数组,能够指定各个元素的类型:
let tuple: [string, number] = ["Alice", 25];
1.6 枚举类型
enum Color {
Red,
Green,
Blue
}
let c: Color = Color.Green;
1.7 Any 类型
any 类型表示可以是任意类型,适用于动态类型的情况:
let notSure: any = 4;
notSure = "Maybe a string instead";
notSure = false; // OK, definitely a boolean
1.8 Void 类型
void 通常用于表示函数没有返回值:
function greet(): void {
console.log("Hello");
}
2. 函数
2.1 函数类型
定义函数类型时,可以指定参数和返回值的类型:
function add(x: number, y: number): number {
return x + y;
}
2.2 可选参数与默认参数
在函数参数列表中,可以通过 ? 来标记可选参数,通过 = 来设定默认参数:
function multiply(x: number, y?: number): number {
return y ? x * y : x;
}
function greet(name: string = "World"): string {
return `Hello, ${name}!`;
}
2.3 剩余参数
使用 ... 语法来处理可变参数的情况:
function sum(...args: number[]): number {
return args.reduce((a, b) => a + b, 0);
}
3. 类和接口
3.1 类
TypeScript 的类语法与 ES6 类语法基本一致,支持继承和修饰符(如 public, private, protected):
class Animal {
private name: string;
constructor(name: string) {
this.name = name;
}
public getName(): string {
return this.name;
}
}
class Dog extends Animal {
bark() {
console.log("Woof!");
}
}
3.2 接口
接口用于定义对象的结构,支持类型检查:
interface Person {
name: string;
age: number;
}
const john: Person = {
name: "John",
age: 30
};
3.3 接口与类的实现
一个类可以实现多个接口,来保证自身能够实现所需的方法:
interface Flyer {
fly(): void;
}
class Bird implements Flyer {
fly() {
console.log("Flying");
}
}
3.4 继承接口
接口支持继承:
interface Animal {
name: string;
}
interface Dog extends Animal {
bark(): void;
}
4. 泛型
泛型使得函数和类可以支持多种数据类型,增加了代码的复用性。
4.1 泛型函数
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString");
let output2 = identity<number>(100);
4.2 泛型类
class Pair<K, V> {
constructor(public key: K, public value: V) {}
}
let pair = new Pair<string, number>("age", 30);
5. 模块
TypeScript 的模块系统允许将代码分成多个文件。可以使用 export 和 import 定义模块关系。
5.1 导出与导入
// module.ts
export class Car {
drive() {
console.log("Driving");
}
}
// app.ts
import { Car } from './module';
const myCar = new Car();
myCar.drive();
5.2 默认导出
export default 用于导出一个默认模块:
// defaultModule.ts
export default class DefaultCar {
drive() {
console.log("Driving default car");
}
}
// app.ts
import DefaultCar from './defaultModule';
const myDefaultCar = new DefaultCar();
myDefaultCar.drive();
6. 装饰器
装饰器是 TypeScript 的一个实验性特性,允许在类和类的方法上增加额外的功能。
6.1 类装饰器
function log(target: Function) {
console.log(`Class ${target.name} is created`);
}
@log
class Person {
constructor(public name: string) {}
}
6.2 方法装饰器
function logMethod(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Method ${propertyName} was called with args: ${args}`);
return originalMethod.apply(this, args);
};
}
class Calculator {
@logMethod
add(x: number, y: number) {
return x + y;
}
}
第三部分:进阶特性
1. 高级类型
1.1 联合类型
可以使用联合类型来定义一个变量可以是多种类型:
let value: string | number;
value = "Hello";
value = 42;
1.2 交叉类型
交叉类型可以组合多个类型,生成一个新类型:
interface A {
a: number;
}
interface B {
b: string;
}
const ab: A & B = { a: 1, b: "hello" };
1.3 类型别名
可以使用type关键字创建类型别名:
type ID = string | number;
2. 类型推断
TypeScript会根据上下文自动推导变量类型,无需显式声明:
let num = 5; // TypeScript推断为number
3. 类型断言
在某些情况下,TypeScript可能无法推断出正确的类型,可以使用类型断言:
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
4. 装饰器
装饰器是TypeScript特有的,用于装饰类、方法或属性的元编程:
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
console.log(`Method ${propertyName} was called`);
}
class Math {
@log
add(x: number, y: number): number {
return x + y;
}
}
5. 模块化
TypeScript支持ES6模块,可以使用import和export来管理模块依赖。
// module.ts
export const PI = 3.14;
export function circleArea(radius: number): number {
return PI * radius * radius;
}
// main.ts
import { PI, circleArea } from './module';
6. 异步编程
TypeScript可以原生支持Promise和async/await,处理异步操作更加简洁:
async function fetchData(): Promise<string> {
const response = await fetch("https://api.example.com");
return await response.text();
}
第三部分:项目实战
1. 创建TypeScript项目
在项目根目录下创建tsconfig.json文件,以配置TypeScript编译选项:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
2. 使用Node.js和TypeScript
TypeScript非常适合Node.js应用开发。可以将TypeScript文件与Node.js结合使用。
npm init -y
npm install express
npm install --save-dev typescript @types/node @types/express
创建一个简单的Express服务器:
// app.ts
import express from 'express';
const app = express();
const PORT = 3000;
app.get('/', (req, res) => {
res.send('Hello TypeScript');
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
3. 使用TypeScript构建React项目
TypeScript与React结合使用可以提升开发体验,安装React和TypeScript:
npx create-react-app my-app --template typescript
在组件中使用TypeScript:
import React from 'react';
interface Props {
title: string;
}
const MyComponent: React.FC<Props> = ({ title }) => {
return <h1>{title}</h1>;
};
export default MyComponent;
4. 测试TypeScript应用
使用Jest进行TypeScript测试,需要安装Jest和ts-jest:
npm install --save-dev jest ts-jest @types/jest
创建jest.config.js配置文件:
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
5. 编写测试用例
使用Jest编写测试用例:
// sum.ts
export const sum = (a: number, b: number): number => a + b;
// sum.test.ts
import { sum } from './sum';
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
6. 在CI/CD中使用TypeScript
可以在CI/CD流程中使用TypeScript进行构建和测试。常见的构建工具有Webpack、Gulp和Grunt。确保在流程中执行tsc命令来编译TypeScript代码。
第四部分:TypeScript最佳实践
1. 明确类型
尽量避免使用any类型,保持类型的明确性,以提高代码质量:
let value: any; // 不推荐
let value: string; // 推荐
2. 使用接口
使用接口定义对象可以提高代码的可读性和可维护性:
interface User {
id: number;
name: string;
}
function getUser(user: User) {
console.log(user.id, user.name);
}
3. 减少代码重复
通过函数和类的重用,来减少代码重复,提高可维护性:
class User {
constructor(public id: number, public name: string) {}
display() {
console.log(this.id, this.name);
}
}
4. 使用抽象类和接口
使用抽象类和接口来定义类的公共行为,提高代码结构的清晰度:
abstract class Shape {
abstract area(): number;
}
class Circle extends Shape {
constructor(private radius: number) {
super();
}
area() {
return Math.PI * this.radius ** 2;
}
}
5. 细化类型定义
根据需求细化类型定义。例如,使用union和intersection类型结合具体业务逻辑进行定义。
type Callback = (value: string) => void;
function execute(value: string, callback: Callback): void {
callback(value);
}
6. 保持代码风格一致
使用格式化工具如Prettier和Linting工具如ESLint保持代码风格一致,增强代码可读性:
npm install --save-dev eslint eslint-config-prettier eslint-plugin-prettier