TypeScript 全面学习指南
目录
- TypeScript 简介
- 环境搭建与工具
- 基础类型
- 变量声明
- 接口(Interfaces)
- 类(Classes)
- 函数(Functions)
- 泛型(Generics)
- 枚举(Enums)
- 类型推论与类型断言
- 高级类型
- 模块(Modules)
- 命名空间(Namespaces)
- 装饰器(Decorators)
- Mixins
- 声明文件(.d.ts)与使用第三方库
- tsconfig.json 配置详解
- 编译与构建
- 调试
- 与JavaScript互操作
- 最佳实践
- 常见问题与解决方案
- 学习资源
1. TypeScript 简介
TypeScript 是 JavaScript 的超集,由微软开发并开源。它添加了静态类型系统和其他特性,使得开发大型应用更加容易。TypeScript 最终编译为纯 JavaScript。
主要特性:
- 静态类型检查
- 类、接口等面向对象特性
- 编译时类型检查
- 支持最新的ECMAScript特性
- 可选的类型系统
2. 环境搭建与工具
安装
npm install -g typescript
编辑器推荐
- Visual Studio Code(内置TS支持)
3. 基础类型
TypeScript 支持 JavaScript 的所有基础类型,并增加了额外的类型:
boolean
: 布尔值number
: 数字(包括二进制、八进制、十进制、十六进制)string
: 字符串array
: 数组(两种写法:number[]
或Array<number>
)tuple
: 元组,例如[string, number]
enum
: 枚举any
: 任意类型(避免使用)void
: 通常用于函数没有返回值null
和undefined
: 所有类型的子类型never
: 表示永远不会出现的值,如抛出异常的函数object
: 非原始类型(非number
,string
,boolean
,symbol
,null
, 或undefined
)
示例:
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let tuple: [string, number] = ["hello", 10]; // 元组
enum Color {Red, Green, Blue} // 枚举
let notSure: any = 4;
function warnUser(): void { console.log("This is a warning"); }
let u: undefined = undefined;
let n: null = null;
4. 变量声明
与 JavaScript 类似,使用 let
和 const
。推荐使用 const
声明常量,let
声明变量。
5. 接口(Interfaces)
接口定义对象的形状(属性、方法等)。
interface Person {
name: string;
age: number;
readonly id: number; // 只读属性
nickname?: string; // 可选属性
greet(phrase: string): void;
}
// 实现接口
const john: Person = {
name: "John",
age: 30,
id: 1234,
greet(phrase: string) {
console.log(`${phrase} ${this.name}`);
}
};
// 函数类型接口
interface SearchFunc {
(source: string, subString: string): boolean;
}
// 可索引类型接口(数组和对象)
interface StringArray {
[index: number]: string;
}
6. 类(Classes)
TypeScript 支持基于类的面向对象编程。
class Animal {
// 成员变量(默认public)
private name: string; // 私有变量,只能在类内部访问
protected age: number; // 受保护变量,可在子类访问
// 构造函数
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 方法
move(distance: number = 0) {
console.log(`${this.name} moved ${distance}m`);
}
}
// 继承
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
// console.log(this.name); // 错误,name是private
console.log(this.age); // 正确,age是protected
}
}
// 抽象类
abstract class Department {
abstract printMeeting(): void; // 抽象方法
}
7. 函数(Functions)
函数类型包含参数类型和返回值类型。
// 函数声明
function add(x: number, y: number): number {
return x + y;
}
// 函数表达式
const myAdd: (x: number, y: number) => number = function(x: number, y: number): number {
return x + y;
};
// 可选参数(必须放在最后)
function buildName(firstName: string, lastName?: string) {
return firstName + (lastName ? ` ${lastName}` : '');
}
// 默认参数
function buildName2(firstName: string, lastName = "Smith") { ... }
// 剩余参数
function buildName3(firstName: string, ...restOfName: string[]) { ... }
// 函数重载
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
8. 泛型(Generics)
泛型用于复用代码,同时保持类型安全。
// 泛型函数
function identity<T>(arg: T): T {
return arg;
}
// 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
// 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
9. 枚举(Enums)
枚举类型用于定义一组命名常量。
// 数字枚举(默认从0开始)
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right // 3
}
// 字符串枚举
enum DirectionStr {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
// 异构枚举(混合字符串和数字,不推荐)
enum BooleanLikeHeterogeneousEnum {
No = 0,
Yes = "YES",
}
10. 类型推论与类型断言
类型推论:TypeScript 会在没有明确指定类型的时候推测出一个类型。 类型断言:告诉编译器“我知道这个变量的类型”。
// 类型推论
let x = 3; // x 被推断为 number
// 类型断言(两种形式)
let someValue: any = "this is a string";
let strLength1: number = (<string>someValue).length;
let strLength2: number = (someValue as string).length; // 推荐在JSX中使用
11. 高级类型
交叉类型(Intersection Types)
function extend<T, U>(first: T, second: U): T & U {
return { ...first, ...second };
}
联合类型(Union Types)
function padLeft(value: string, padding: string | number) { ... }
类型别名(Type Aliases)
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
字符串字面量类型
type Easing = "ease-in" | "ease-out" | "ease-in-out";
可辨识联合(Discriminated Unions)
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
type Shape = Square | Rectangle;
索引类型(Index Types)
function pluck<T, K extends keyof T>(obj: T, keys: K[]): T[K][] {
return keys.map(key => obj[key]);
}
映射类型(Mapped Types)
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
条件类型(Conditional Types)
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
"object";
12. 模块(Modules)
TypeScript 支持 ES6 模块语法。
// 导出
export interface Person { ... }
export class Employee { ... }
export default function() { ... }
// 导入
import { Person } from "./module";
import Employee from "./module"; // 默认导入
import * as Module from "./module";
13. 命名空间(Namespaces)
命名空间用于组织代码,以避免全局作用域污染。但在 ES6 模块化后,推荐使用模块。
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}
14. 装饰器(Decorators)
装饰器是一种特殊类型的声明,用于附加到类、方法、属性或参数上。需要启用 experimentalDecorators
选项。
// 类装饰器
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
}
// 方法装饰器
function enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class Greeter2 {
@enumerable(false)
greet() { ... }
}
15. Mixins
Mixins 是一种实现多重继承的方式。
class Disposable {
isDisposed: boolean = false;
dispose() { this.isDisposed = true; }
}
class Activatable {
isActive: boolean = false;
activate() { this.isActive = true; }
}
class SmartObject implements Disposable, Activatable {
// Disposable
isDisposed: boolean = false;
dispose!: () => void;
// Activatable
isActive: boolean = false;
activate!: () => void;
}
applyMixins(SmartObject, [Disposable, Activatable]);
// 混入函数
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
});
});
}
16. 声明文件(.d.ts)与使用第三方库
声明文件(Declaration Files)用于描述已有 JavaScript 库的类型信息。
安装 DefinitelyTyped 的类型声明:
npm install --save-dev @types/node
npm install --save-dev @types/lodash
自己编写声明文件:
// myLib.d.ts
declare module "myLib" {
export function makeGreeting(s: string): string;
export let numberOfGreetings: number;
}
17. tsconfig.json 配置详解
{
"compilerOptions": {
"target": "es5", // 编译目标ES版本
"module": "commonjs", // 模块系统
"strict": true, // 启用所有严格类型检查
"noImplicitAny": true, // 禁止隐式any
"strictNullChecks": true, // 严格空值检查
"esModuleInterop": true, // 支持CommonJS和ES模块互操作
"outDir": "dist", // 输出目录
"declaration": true // 生成声明文件
},
"include": ["src/**/*.ts"], // 包含的文件
"exclude": ["node_modules"] // 排除的文件
}
18. 编译与构建
tsc # 编译所有项目文件
tsc --watch # 监视模式
tsc --project tsconfig.json # 指定配置文件
19. 调试
在 VS Code 中,配置 launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/dist/index.js",
"preLaunchTask": "tsc: build - tsconfig.json",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
]
}
20. 与JavaScript互操作
TypeScript 可以直接引入 JavaScript 文件,但需要类型声明(通过声明文件)。
21. 最佳实践
- 尽量使用
interface
而非type
定义对象类型(接口可扩展) - 开启严格模式(
strict: true
) - 避免使用
any
,优先使用更精确的类型 - 使用泛型提高代码复用性
- 使用模块而非命名空间
22. 常见问题与解决方案
-
错误:Element implicitly has an 'any' type
原因:没有为变量指定类型,且无法推断。
解决:显式声明类型或启用noImplicitAny: false
(不推荐)。 -
错误:Cannot find module 'xxx'
解决:安装对应的类型声明文件(@types/xxx
)或自己编写声明文件。 -
错误:Property 'xxx' does not exist on type 'yyy'
解决:检查类型声明,可能需要扩展接口。
23. 学习资源
- TypeScript 官方文档
- TypeScript Deep Dive
- TypeScript Playground
- Type Challenges