TypeScript使用指南
概述
TypeScript是JavaScript的超集,添加了静态类型检查和现代JavaScript特性。它由Microsoft开发,旨在提高大型JavaScript应用的可维护性和开发效率。本指南将全面介绍TypeScript的核心概念和实际应用。
1. TypeScript基础
1.1 什么是TypeScript
TypeScript是JavaScript的类型化超集,编译成纯JavaScript。主要特性:
- 静态类型检查:在编译时发现类型错误
- 现代JavaScript特性:支持ES6+特性
- 强大的工具支持:智能提示、重构、导航
- 更好的代码组织:接口、类、模块等
1.2 安装和配置
# 全局安装TypeScript
npm install -g typescript
# 项目中安装
npm install --save-dev typescript
# 初始化TypeScript项目
npx tsc --init
# 编译TypeScript文件
tsc filename.ts
# 监听模式编译
tsc filename.ts --watch
# 使用ts-node直接运行
npm install -g ts-node
ts-node filename.ts
1.3 tsconfig.json配置
{
"compilerOptions": {
"target": "ES2020", // 编译目标版本
"module": "commonjs", // 模块系统
"lib": ["ES2020", "DOM"], // 包含的库
"outDir": "./dist", // 输出目录
"rootDir": "./src", // 源码目录
"strict": true, // 启用严格模式
"esModuleInterop": true, // ES模块互操作
"skipLibCheck": true, // 跳过库文件检查
"forceConsistentCasingInFileNames": true,
"declaration": true, // 生成声明文件
"sourceMap": true, // 生成源码映射
"removeComments": true, // 移除注释
"noImplicitAny": true, // 禁止隐式any
"strictNullChecks": true, // 严格空值检查
"strictFunctionTypes": true, // 严格函数类型
"noImplicitReturns": true, // 函数必须有返回值
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node", // 模块解析策略
"baseUrl": "./", // 基础路径
"paths": { // 路径映射
"@/*": ["src/*"]
}
},
"include": ["src/**/*"], // 包含的文件
"exclude": ["node_modules"] // 排除的文件
}
2. 基础类型
2.1 基本类型
// 原始类型
let isDone: boolean = false;
let decimal: number = 6;
let color: string = "blue";
let list: number[] = [1, 2, 3];
let x: [string, number] = ["hello", 10]; // 元组
// 枚举
enum Color { Red, Green, Blue }
let c: Color = Color.Green;
enum Status {
Pending = "pending",
Approved = "approved",
Rejected = "rejected"
}
// any类型(尽量避免使用)
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;
// unknown类型(更安全的any)
let value: unknown = 4;
if (typeof value === "number") {
console.log(value * 2); // 需要类型检查
}
// void类型
function warnUser(): void {
console.log("This is a warning message");
}
// null和undefined
let u: undefined = undefined;
let n: null = null;
// never类型
function error(message: string): never {
throw new Error(message);
}
// object类型
let obj: object = { name: "John" };
let person: { name: string; age: number } = {
name: "John",
age: 30
};
2.2 类型注解和推断
// 类型注解
let name: string = "John";
let age: number = 30;
let isActive: boolean = true;
// 类型推断
let inferred = "TypeScript"; // 推断为string
let number = 42; // 推断为number
// 函数类型注解
function greet(name: string): string {
return `Hello, ${name}!`;
}
// 可选参数
function greetOptional(name?: string): string {
return name ? `Hello, ${name}!` : "Hello, stranger!";
}
// 默认参数
function greetDefault(name: string = "Guest"): string {
return `Hello, ${name}!`;
}
// 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((a, b) => a + b, 0);
}
3. 接口和类型别名
3.1 接口定义
// 基本接口
interface Person {
name: string;
age: number;
}
// 可选属性
interface User {
id: number;
name: string;
email?: string; // 可选属性
}
// 只读属性
interface Config {
readonly apiUrl: string;
readonly timeout: number;
}
// 函数类型接口
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc = function(source: string, subString: string): boolean {
return source.search(subString) > -1;
};
// 索引签名
interface StringArray {
[index: number]: string;
}
let myArray: StringArray = ["Bob", "Fred"];
// 混合类型接口
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = (function(start: number) { return start.toString(); }) as Counter;
counter.interval = 123;
counter.reset = function() { console.log("Reset"); };
return counter;
}
3.2 接口继承
// 基本继承
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
let square: Square = {
color: "blue",
sideLength: 10
};
// 多重继承
interface PenStroke {
penWidth: number;
}
interface Circle extends Shape, PenStroke {
radius: number;
}
// 接口实现
interface ClockInterface {
currentTime: Date;
setTime(d: Date): void;
}
class Clock implements ClockInterface {
currentTime: Date = new Date();
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) {}
}
3.3 类型别名
// 基本类型别名
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === "string") {
return n;
} else {
return n();
}
}
// 对象类型别名
type Person = {
name: string;
age: number;
address?: {
street: string;
city: string;
};
};
// 联合类型
type Status = "pending" | "approved" | "rejected";
type ID = string | number;
// 泛型类型别名
type Container<T> = { value: T };
type Tree<T> = {
value: T;
left?: Tree<T>;
right?: Tree<T>;
};
// 条件类型
type IsString<T> = T extends string ? true : false;
type Result = IsString<"hello">; // true
// 映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 使用示例
interface User {
id: number;
name: string;
email: string;
}
type ReadonlyUser = Readonly<User>;
type PartialUser = Partial<User>;
4. 类
4.1 类的基本语法
// 基本类定义
class Greeter {
// 属性
greeting: string;
// 构造函数
constructor(message: string) {
this.greeting = message;
}
// 方法
greet(): string {
return `Hello, ${this.greeting}`;
}
}
let greeter = new Greeter("world");
console.log(greeter.greet());
// 继承
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
constructor(name: string) {
super(name); // 调用父类构造函数
}
move(distanceInMeters = 5) {
console.log("Dog is running...");
super.move(distanceInMeters);
}
bark() {
console.log("Woof! Woof!");
}
}
let dog = new Dog("Buddy");
dog.bark();
dog.move(10);
4.2 访问修饰符
class Person {
public name: string; // 公共属性(默认)
private age: number; // 私有属性
protected gender: string; // 受保护属性
readonly id: number; // 只读属性
constructor(name: string, age: number, gender: string, id: number) {
this.name = name;
this.age = age;
this.gender = gender;
this.id = id;
}
public getInfo(): string {
return `${this.name} (${this.age})`;
}
private getAge(): number {
return this.age;
}
protected getGender(): string {
return this.gender;
}
}
class Employee extends Person {
private salary: number;
constructor(name: string, age: number, gender: string, id: number, salary: number) {
super(name, age, gender, id);
this.salary = salary;
}
public getEmployeeInfo(): string {
// 可以访问protected属性
return `${this.name} - ${this.getGender()} - $${this.salary}`;
}
}
// 参数属性(简化写法)
class Student {
constructor(
public firstName: string,
private lastName: string,
protected grade: number
) {}
getFullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
4.3 静态属性和方法
class MathHelper {
static PI: number = 3.14159;
static calculateCircleArea(radius: number): number {
return MathHelper.PI * radius * radius;
}
static isEven(num: number): boolean {
return num % 2 === 0;
}
}
// 使用静态成员
console.log(MathHelper.PI);
console.log(MathHelper.calculateCircleArea(5));
console.log(MathHelper.isEven(4));
class Counter {
private static count: number = 0;
constructor() {
Counter.count++;
}
public static getCount(): number {
return Counter.count;
}
}
let c1 = new Counter();
let c2 = new Counter();
console.log(Counter.getCount()); // 2
4.4 抽象类
abstract class Animal {
abstract name: string;
abstract makeSound(): void; // 抽象方法
move(): void { // 具体方法
console.log(`${this.name} is moving`);
}
}
class Cat extends Animal {
name: string = "Cat";
makeSound(): void {
console.log("Meow!");
}
purr(): void {
console.log("Purrr...");
}
}
let cat = new Cat();
cat.makeSound();
cat.move();
cat.purr();
// 抽象类不能直接实例化
// let animal = new Animal(); // 错误
5. 泛型
5.1 泛型函数
// 基本泛型函数
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString");
let output2 = identity<number>(100);
let output3 = identity("myString"); // 类型推断
// 泛型约束
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在知道arg有length属性
return arg;
}
loggingIdentity("hello"); // 可以
loggingIdentity([1, 2, 3]); // 可以
// loggingIdentity(3); // 错误,没有length属性
// 多个类型参数
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
let pairResult = pair<string, number>("hello", 42);
5.2 泛型类
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
isEmpty(): boolean {
return this.items.length === 0;
}
size(): number {
return this.items.length;
}
}
let numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // 2
let stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");
console.log(stringStack.pop()); // "world"
5.3 泛型接口
interface GenericIdentityFn<T> {
(arg: T): T;
}
let myIdentity: GenericIdentityFn<number> = identity;
interface Repository<T> {
findById(id: number): Promise<T>;
save(entity: T): Promise<T>;
delete(id: number): Promise<void>;
}
class UserRepository implements Repository<User> {
async findById(id: number): Promise<User> {
// 实现查找用户逻辑
return {} as User;
}
async save(user: User): Promise<User> {
// 实现保存用户逻辑
return user;
}
async delete(id: number): Promise<void> {
// 实现删除用户逻辑
}
}
6. 高级类型
6.1 联合类型和交叉类型
// 联合类型
type Status = "loading" | "success" | "error";
function handleStatus(status: Status): string {
switch (status) {
case "loading":
return "Loading...";
case "success":
return "Success!";
case "error":
return "Error occurred";
}
}
// 联合类型与类型守卫
interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
type Pet = Bird | Fish;
function isBird(pet: Pet): pet is Bird {
return (pet as Bird).fly !== undefined;
}
function handlePet(pet: Pet): void {
if (isBird(pet)) {
pet.fly();
} else {
pet.swim();
}
}
// 交叉类型
interface Person {
name: string;
age: number;
}
interface Employee {
id: number;
department: string;
}
type EmployeePerson = Person & Employee;
let employee: EmployeePerson = {
name: "John",
age: 30,
id: 123,
department: "IT"
};
6.2 条件类型
// 基本条件类型
type IsString<T> = T extends string ? true : false;
type Test1 = IsString<string>; // true
type Test2 = IsString<number>; // false
// 条件类型与泛型
type NonNullable<T> = T extends null | undefined ? never : T;
type Test3 = NonNullable<string | null>; // string
type Test4 = NonNullable<number | undefined>; // number
// 映射条件类型
type ExtractType<T, U> = T extends U ? T : never;
type Test5 = ExtractType<string | number | boolean, string | number>; // string | number
// 推断条件类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function greet(): string {
return "Hello";
}
type GreetReturn = ReturnType<typeof greet>; // string
6.3 映射类型
// 基本映射类型
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
// 使用示例
interface User {
id: number;
name: string;
email: string;
}
type ReadonlyUser = Readonly<User>;
type PartialUser = Partial<User>;
// 自定义映射类型
type Stringify<T> = {
[K in keyof T]: string;
};
type StringifiedUser = Stringify<User>;
// 条件映射类型
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type UserGetters = Getters<User>;
// {
// getId: () => number;
// getName: () => string;
// getEmail: () => string;
// }
7. 装饰器
7.1 类装饰器
// 基本类装饰器
function classDecorator<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
newProperty = "new property";
hello = "override";
};
}
@classDecorator
class Greeter {
property = "original property";
hello = "original hello";
}
console.log(new Greeter().hello); // "override"
// 带参数的类装饰器
function entity(tableName: string) {
return function<T extends { new(...args: any[]): {} }>(constructor: T) {
return class extends constructor {
tableName = tableName;
};
};
}
@entity("users")
class User {
constructor(public name: string, public email: string) {}
}
console.log((new User("John", "john@example.com") as any).tableName); // "users"
7.2 方法装饰器
function log(target: any, propertyName: string, descriptor: PropertyDescriptor) {
const method = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${propertyName} with args: ${JSON.stringify(args)}`);
const result = method.apply(this, args);
console.log(`${propertyName} returned: ${JSON.stringify(result)}`);
return result;
};
}
class Calculator {
@log
add(a: number, b: number): number {
return a + b;
}
@log
multiply(a: number, b: number): number {
return a * b;
}
}
const calc = new Calculator();
calc.add(2, 3); // 输出日志
calc.multiply(4, 5); // 输出日志
7.3 属性装饰器
function validate(target: any, propertyName: string) {
let value: string;
const getter = () => value;
const setter = (newValue: string) => {
if (newValue.length < 3) {
throw new Error(`${propertyName} must be at least 3 characters long`);
}
value = newValue;
};
Object.defineProperty(target, propertyName, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
class Person {
@validate
name: string;
constructor(name: string) {
this.name = name;
}
}
try {
const person = new Person("Jo"); // 抛出错误
} catch (error) {
console.error(error.message);
}
8. 模块和命名空间
8.1 ES模块
// math.ts
export const PI = 3.14159;
export function add(a: number, b: number): number {
return a + b;
}
export function multiply(a: number, b: number): number {
return a * b;
}
export class Calculator {
divide(a: number, b: number): number {
return a / b;
}
}
// 默认导出
export default class MathUtils {
static power(base: number, exponent: number): number {
return Math.pow(base, exponent);
}
}
// main.ts
import MathUtils, { PI, add, multiply, Calculator } from './math';
console.log(PI);
console.log(add(2, 3));
console.log(multiply(4, 5));
const calc = new Calculator();
console.log(calc.divide(10, 2));
console.log(MathUtils.power(2, 3));
// 重命名导入
import { add as sum } from './math';
console.log(sum(1, 2));
// 导入整个模块
import * as Math from './math';
console.log(Math.PI);
console.log(Math.add(1, 2));
8.2 命名空间
// shapes.ts
namespace Shapes {
export interface Point {
x: number;
y: number;
}
export class Circle {
constructor(public center: Point, public radius: number) {}
area(): number {
return Math.PI * this.radius * this.radius;
}
}
export namespace Utils {
export function distance(p1: Point, p2: Point): number {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
}
}
// 使用命名空间
const center: Shapes.Point = { x: 0, y: 0 };
const circle = new Shapes.Circle(center, 5);
console.log(circle.area());
const p1: Shapes.Point = { x: 0, y: 0 };
const p2: Shapes.Point = { x: 3, y: 4 };
console.log(Shapes.Utils.distance(p1, p2));
// 嵌套命名空间
namespace MyApplication {
export namespace Models {
export interface User {
id: number;
name: string;
}
}
export namespace Services {
export class UserService {
private users: Models.User[] = [];
addUser(user: Models.User): void {
this.users.push(user);
}
getUsers(): Models.User[] {
return this.users;
}
}
}
}
9. 异步编程
9.1 Promise和async/await
// 基本Promise
function fetchData(url: string): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url) {
resolve(`Data from ${url}`);
} else {
reject(new Error("URL is required"));
}
}, 1000);
});
}
// 使用Promise
fetchData("https://api.example.com")
.then(data => console.log(data))
.catch(error => console.error(error));
// async/await
async function fetchDataAsync(url: string): Promise<string> {
try {
const data = await fetchData(url);
console.log(data);
return data;
} catch (error) {
console.error("Error:", error);
throw error;
}
}
// 并行执行
async function fetchMultipleData(): Promise<string[]> {
const urls = [
"https://api.example.com/1",
"https://api.example.com/2",
"https://api.example.com/3"
];
try {
const results = await Promise.all(urls.map(url => fetchData(url)));
return results;
} catch (error) {
console.error("Error fetching data:", error);
throw error;
}
}
// 竞争执行
async function fetchFirstAvailable(): Promise<string> {
const urls = [
"https://api.example.com/1",
"https://api.example.com/2",
"https://api.example.com/3"
];
try {
const result = await Promise.race(urls.map(url => fetchData(url)));
return result;
} catch (error) {
console.error("All requests failed:", error);
throw error;
}
}
9.2 类型化异步操作
// 类型化的API响应
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
interface User {
id: number;
name: string;
email: string;
}
// 类型化的API函数
async function fetchUser(id: number): Promise<ApiResponse<User>> {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data: ApiResponse<User> = await response.json();
return data;
}
// 使用类型化API
async function displayUser(id: number): Promise<void> {
try {
const response = await fetchUser(id);
const user = response.data;
console.log(`User: ${user.name} (${user.email})`);
} catch (error) {
console.error("Failed to fetch user:", error);
}
}
// 泛型API客户端
class ApiClient {
private baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
async get<T>(endpoint: string): Promise<ApiResponse<T>> {
const response = await fetch(`${this.baseUrl}${endpoint}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
async post<T>(endpoint: string, data: any): Promise<ApiResponse<T>> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
}
// 使用API客户端
const apiClient = new ApiClient('https://api.example.com');
async function createUser(userData: Omit<User, 'id'>): Promise<User> {
const response = await apiClient.post<User>('/users', userData);
return response.data;
}
10. 错误处理
10.1 类型化错误
// 自定义错误类
class CustomError extends Error {
constructor(
message: string,
public code: string,
public statusCode: number = 500
) {
super(message);
this.name = 'CustomError';
}
}
class ValidationError extends CustomError {
constructor(
message: string,
public field: string
) {
super(message, 'VALIDATION_ERROR', 400);
this.name = 'ValidationError';
}
}
// 错误处理函数
function handleError(error: unknown): void {
if (error instanceof ValidationError) {
console.error(`Validation error in field ${error.field}: ${error.message}`);
} else if (error instanceof CustomError) {
console.error(`${error.code}: ${error.message}`);
} else if (error instanceof Error) {
console.error(`Unexpected error: ${error.message}`);
} else {
console.error('Unknown error occurred');
}
}
// Result类型(函数式错误处理)
type Result<T, E = Error> = {
success: true;
data: T;
} | {
success: false;
error: E;
};
function safeParseInt(str: string): Result<number, Error> {
const num = parseInt(str, 10);
if (isNaN(num)) {
return {
success: false,
error: new Error(`Cannot parse "${str}" as integer`)
};
}
return {
success: true,
data: num
};
}
// 使用Result类型
function processNumber(input: string): void {
const result = safeParseInt(input);
if (result.success) {
console.log(`Parsed number: ${result.data}`);
} else {
console.error(`Error: ${result.error.message}`);
}
}
10.2 异步错误处理
// 异步Result类型
type AsyncResult<T, E = Error> = Promise<Result<T, E>>;
async function safeFetch(url: string): AsyncResult<any> {
try {
const response = await fetch(url);
if (!response.ok) {
return {
success: false,
error: new Error(`HTTP error! status: ${response.status}`)
};
}
const data = await response.json();
return {
success: true,
data
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error : new Error('Unknown error')
};
}
}
// 使用异步Result
async function fetchUserData(userId: number): Promise<void> {
const result = await safeFetch(`/api/users/${userId}`);
if (result.success) {
console.log('User data:', result.data);
} else {
console.error('Failed to fetch user:', result.error.message);
}
}
// 错误边界装饰器
function withErrorHandling<T extends any[], R>(
fn: (...args: T) => Promise<R>
) {
return async (...args: T): Promise<Result<R>> => {
try {
const result = await fn(...args);
return {
success: true,
data: result
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error : new Error('Unknown error')
};
}
};
}
// 使用错误边界装饰器
const safeFetchUser = withErrorHandling(async (id: number) => {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`Failed to fetch user: ${response.status}`);
}
return response.json();
});
async function getUserData(id: number): Promise<void> {
const result = await safeFetchUser(id);
if (result.success) {
console.log('User:', result.data);
} else {
console.error('Error:', result.error.message);
}
}
11. 工具类型
11.1 内置工具类型
// Partial<T> - 将T的所有属性变为可选
interface Todo {
title: string;
description: string;
completed: boolean;
}
type PartialTodo = Partial<Todo>;
// { title?: string; description?: string; completed?: boolean; }
// Required<T> - 将T的所有属性变为必需
type RequiredTodo = Required<Todo>;
// { title: string; description: string; completed: boolean; }
// Readonly<T> - 将T的所有属性变为只读
type ReadonlyTodo = Readonly<Todo>;
// { readonly title: string; readonly description: string; readonly completed: boolean; }
// Record<K, T> - 创建键为K类型,值为T类型的对象
type UserRoles = Record<string, boolean>;
// { [key: string]: boolean; }
// Pick<T, K> - 从T中选择一组属性K来创建类型
type TodoPreview = Pick<Todo, 'title' | 'completed'>;
// { title: string; completed: boolean; }
// Omit<T, K> - 从T中排除一组属性K来创建类型
type TodoWithoutDescription = Omit<Todo, 'description'>;
// { title: string; completed: boolean; }
// Exclude<T, U> - 从T中排除可分配给U的类型
type Primitive = string | number | boolean;
type NonStringPrimitive = Exclude<Primitive, string>;
// number | boolean
// Extract<T, U> - 从T中提取可分配给U的类型
type StringPrimitive = Extract<Primitive, string>;
// string
// NonNullable<T> - 从T中排除null和undefined
type NonNullableString = NonNullable<string | null | undefined>;
// string
// ReturnType<T> - 获取函数类型T的返回类型
type FunctionType = (a: number, b: number) => string;
type Return = ReturnType<FunctionType>;
// string
// Parameters<T> - 获取函数类型T的参数类型
type Params = Parameters<FunctionType>;
// [a: number, b: number]
// InstanceType<T> - 获取构造函数类型T的实例类型
class MyClass {
constructor(public name: string) {}
}
type MyInstance = InstanceType<typeof MyClass>;
// MyClass
11.2 自定义工具类型
// 深度Partial
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
interface Nested {
a: {
b: {
c: string;
};
};
}
type PartialNested = DeepPartial<Nested>;
// { a?: { b?: { c?: string } } }
// 深度Readonly
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
// 条件类型:提取数组元素类型
type ArrayElement<T> = T extends (infer U)[] ? U : never;
type StringArray = string[];
type ElementType = ArrayElement<StringArray>; // string
// 条件类型:提取Promise解析值类型
type PromiseValue<T> = T extends Promise<infer U> ? U : never;
type StringPromise = Promise<string>;
type ResolvedType = PromiseValue<StringPromise>; // string
// 联合类型转交叉类型
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never;
// 获取函数参数的最后一个类型
type LastParameter<T> = T extends (...args: infer A) => any
? A extends [...any, infer L]
? L
: never
: never;
type Func = (a: string, b: number, c: boolean) => void;
type LastParam = LastParameter<Func>; // boolean
// 创建可选的深度路径类型
type DeepPath<T, Path extends string> = Path extends keyof T
? T[Path]
: Path extends `${infer Key}.${infer Rest}`
? Key extends keyof T
? DeepPath<T[Key], Rest>
: never
: never;
interface User {
id: number;
profile: {
name: string;
address: {
city: string;
country: string;
};
};
}
type CityType = DeepPath<User, 'profile.address.city'>; // string
12. 配置和构建
12.1 TypeScript配置最佳实践
{
"compilerOptions": {
// 基础配置
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
// 输出配置
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": false,
// 严格类型检查
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
// 额外检查
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
// 高级配置
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"incremental": true,
"tsBuildInfoFile": "./dist/.tsbuildinfo"
},
"include": [
"src/**/*",
"types/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts",
"**/*.spec.ts"
]
}
12.2 构建工具集成
// package.json
{
"name": "typescript-project",
"version": "1.0.0",
"scripts": {
"build": "tsc",
"build:watch": "tsc --watch",
"dev": "ts-node src/index.ts",
"start": "node dist/index.js",
"clean": "rimraf dist",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint src/**/*.ts --fix",
"test": "jest",
"test:watch": "jest --watch"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/jest": "^28.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.0",
"jest": "^28.0.0",
"rimraf": "^3.0.0",
"ts-jest": "^28.0.0",
"ts-node": "^10.0.0",
"typescript": "^4.8.0"
}
}
12.3 ESLint配置
// .eslintrc.json
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"@typescript-eslint/recommended",
"@typescript-eslint/recommended-requiring-type-checking"
],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/prefer-nullish-coalescing": "error",
"@typescript-eslint/prefer-optional-chain": "error"
}
}
13. 实际应用示例
13.1 类型安全的API客户端
// api-client.ts
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
interface User {
id: number;
name: string;
email: string;
createdAt: string;
}
interface CreateUserRequest {
name: string;
email: string;
password: string;
}
class ApiClient {
private baseUrl: string;
private headers: Record<string, string>;
constructor(baseUrl: string, apiKey?: string) {
this.baseUrl = baseUrl;
this.headers = {
'Content-Type': 'application/json',
...(apiKey && { 'Authorization': `Bearer ${apiKey}` })
};
}
private async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const url = `${this.baseUrl}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
...this.headers,
...options.headers
}
});
if (!response.ok) {
throw new Error(`API request failed: ${response.status} ${response.statusText}`);
}
return response.json();
}
async get<T>(endpoint: string): Promise<T> {
const response = await this.request<T>(endpoint);
return response.data;
}
async post<T>(endpoint: string, data: any): Promise<T> {
const response = await this.request<T>(endpoint, {
method: 'POST',
body: JSON.stringify(data)
});
return response.data;
}
async put<T>(endpoint: string, data: any): Promise<T> {
const response = await this.request<T>(endpoint, {
method: 'PUT',
body: JSON.stringify(data)
});
return response.data;
}
async delete<T>(endpoint: string): Promise<T> {
const response = await this.request<T>(endpoint, {
method: 'DELETE'
});
return response.data;
}
}
// 使用示例
class UserService {
private client: ApiClient;
constructor(baseUrl: string, apiKey?: string) {
this.client = new ApiClient(baseUrl, apiKey);
}
async getUsers(): Promise<User[]> {
return this.client.get<User[]>('/users');
}
async getUserById(id: number): Promise<User> {
return this.client.get<User>(`/users/${id}`);
}
async createUser(userData: CreateUserRequest): Promise<User> {
return this.client.post<User>('/users', userData);
}
async updateUser(id: number, userData: Partial<User>): Promise<User> {
return this.client.put<User>(`/users/${id}`, userData);
}
async deleteUser(id: number): Promise<void> {
return this.client.delete<void>(`/users/${id}`);
}
}
13.2 状态管理示例
// store.ts
type State = {
user: User | null;
isLoading: boolean;
error: string | null;
};
type Action =
| { type: 'SET_LOADING'; payload: boolean }
| { type: 'SET_USER'; payload: User }
| { type: 'SET_ERROR'; payload: string }
| { type: 'CLEAR_ERROR' };
class Store {
private state: State;
private listeners: Array<(state: State) => void> = [];
constructor(initialState: State) {
this.state = initialState;
}
getState(): State {
return { ...this.state };
}
dispatch(action: Action): void {
this.state = this.reducer(this.state, action);
this.notify();
}
subscribe(listener: (state: State) => void): () => void {
this.listeners.push(listener);
return () => {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
};
}
private reducer(state: State, action: Action): State {
switch (action.type) {
case 'SET_LOADING':
return { ...state, isLoading: action.payload };
case 'SET_USER':
return { ...state, user: action.payload, isLoading: false, error: null };
case 'SET_ERROR':
return { ...state, error: action.payload, isLoading: false };
case 'CLEAR_ERROR':
return { ...state, error: null };
default:
return state;
}
}
private notify(): void {
this.listeners.forEach(listener => listener(this.getState()));
}
}
// 使用示例
const store = new Store({
user: null,
isLoading: false,
error: null
});
// 订阅状态变化
const unsubscribe = store.subscribe((state) => {
console.log('State changed:', state);
});
// 派发动作
store.dispatch({ type: 'SET_LOADING', payload: true });
store.dispatch({ type: 'SET_USER', payload: { id: 1, name: 'John', email: 'john@example.com', createdAt: '2023-01-01' } });
14. 最佳实践
14.1 代码组织
// types/index.ts
export interface User {
id: number;
name: string;
email: string;
}
export interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// utils/validation.ts
export interface ValidationRule<T> {
validate: (value: T) => boolean;
message: string;
}
export function validateField<T>(
value: T,
rules: ValidationRule<T>[]
): string[] {
return rules
.filter(rule => !rule.validate(value))
.map(rule => rule.message);
}
// services/user-service.ts
import { User, ApiResponse } from '../types';
export class UserService {
// 实现用户服务
}
// components/user-form.ts
import { User } from '../types';
import { validateField, ValidationRule } from '../utils/validation';
export class UserForm {
private rules: ValidationRule<string>[] = [
{
validate: (value) => value.length >= 3,
message: 'Name must be at least 3 characters'
}
];
validateName(name: string): string[] {
return validateField(name, this.rules);
}
}
14.2 性能优化
// 使用类型守卫优化运行时检查
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function processValue(value: unknown): string {
if (isString(value)) {
return value.toUpperCase();
}
return String(value);
}
// 使用泛型避免重复代码
interface Repository<T> {
findById(id: number): Promise<T>;
save(entity: T): Promise<T>;
delete(id: number): Promise<void>;
}
class BaseRepository<T> implements Repository<T> {
constructor(private apiUrl: string) {}
async findById(id: number): Promise<T> {
const response = await fetch(`${this.apiUrl}/${id}`);
return response.json();
}
async save(entity: T): Promise<T> {
const response = await fetch(this.apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(entity)
});
return response.json();
}
async delete(id: number): Promise<void> {
await fetch(`${this.apiUrl}/${id}`, { method: 'DELETE' });
}
}
// 使用记忆化优化计算密集型操作
function memoize<T extends (...args: any[]) => any>(fn: T): T {
const cache = new Map();
return ((...args: any[]) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
}) as T;
}
const expensiveCalculation = memoize((n: number): number => {
console.log('Performing expensive calculation...');
return n * n;
});
15. 总结
TypeScript为JavaScript开发带来了强大的类型系统和现代编程特性。通过掌握以下核心概念,您可以构建更安全、更可维护的应用程序:
核心优势
- 类型安全:在编译时发现错误,减少运行时问题
- 更好的工具支持:智能提示、重构、代码导航
- 代码可读性:明确的类型注解提高代码可理解性
- 大型项目支持:模块化、接口、命名空间等特性
关键概念
- 基础类型系统:原始类型、接口、类、泛型
- 高级类型:联合类型、交叉类型、条件类型、映射类型
- 异步编程:类型化的Promise和async/await
- 模块系统:ES模块和命名空间
- 工具类型:内置和自定义工具类型
最佳实践
- 启用严格模式:使用
strict: true获得最佳类型检查 - 避免any类型:使用unknown或具体类型替代
- 使用接口定义契约:明确数据结构和API契约
- 合理使用泛型:提高代码复用性和类型安全
- 配置适当的构建工具:ESLint、Prettier、Jest等
TypeScript的学习曲线相对平缓,但深度很大。建议从基础开始,逐步掌握高级特性,并在实际项目中不断实践和优化。通过持续学习和应用,您将能够充分发挥TypeScript的强大功能,构建高质量的JavaScript应用程序。
13 0
评论 (0)
请先登录后再评论
暂无评论