TypeScript高級知識入門教程
本文深入探讨了TypeScript高级知识,包括泛型、高级类型特性、装饰器应用和模块化编程等内容。文章还提供了类型推断与类型断言的最佳实践以及项目结构建议,并详细解释了TypeScript配置文件的使用方法。通过这些内容,读者可以掌握编写高效且安全TypeScript代码的关键技巧。
TypeScript高级知识入门教程 TypeScript 基础回顾变量声明与类型注解
TypeScript 是 JavaScript 的一个超集,它添加了静态类型检查,使代码更安全且易于维护。在 TypeScript 中,变量声明时需要指定类型,这有助于开发人员和编译器更好地理解代码意图。
下面是一个简单的变量声明示例:
let num: number = 42;
const message: string = "Hello, TypeScript!";
let isTrue: boolean = true;
console.log(num, message, isTrue);
函数定义与调用
在 TypeScript 中,函数的定义需要明确指定返回类型和参数类型。这有助于在编译时进行类型检查,防止类型错误。
例如:
function add(a: number, b: number): number {
return a + b;
}
let result: number = add(10, 20);
console.log(result); // 输出 30
类与接口简介
TypeScript 中的类和接口是创建自定义类型的主要工具。类用于定义对象和它们的行为,而接口用于定义对象的结构。
下面是一个简单的类和接口的示例:
interface Person {
name: string;
age: number;
}
class Student implements Person {
name: string;
age: number;
grade: string;
constructor(name: string, age: number, grade: string) {
this.name = name;
this.age = age;
this.grade = grade;
}
}
let student: Person = new Student("Alice", 20, "A");
console.log(student.name, student.age); // 输出 Alice 20
泛型详解
泛型的基本概念
泛型是一种可以接受任意类型的编程模式,它允许创建可以处理多种数据类型的通用代码。泛型通常在函数、类和接口中使用,使代码更具灵活度和重用性。
下面是一个简单的泛型函数示例:
function first<T>(arr: T[]): T {
return arr[0];
}
let numbers: number[] = [1, 2, 3];
console.log(first(numbers)); // 输出 1
let strings: string[] = ["a", "b", "c"];
console.log(first(strings)); // 输出 a
在函数中的应用
泛型在函数中应用广泛,它可以处理不同类型的数据。例如,一个函数可能需要返回数组的第一个元素,但这个数组可以是任何类型的数据。
function last<T>(arr: T[]): T {
return arr[arr.length - 1];
}
let numbers: number[] = [1, 2, 3];
console.log(last(numbers)); // 输出 3
let strings: string[] = ["a", "b", "c"];
console.log(last(strings)); // 输出 c
在类和接口中的应用
在类和接口中使用泛型可以增强代码的灵活性。例如,一个容器类可以接受任何类型的元素,而接口可以定义一个通用的类型结构。
泛型类示例
class List<T> {
items: T[] = [];
add(item: T) {
this.items.push(item);
}
get(index: number): T {
return this.items[index];
}
}
let numberList = new List<number>();
numberList.add(1);
numberList.add(2);
console.log(numberList.get(0)); // 输出 1
let stringList = new List<string>();
stringList.add("a");
stringList.add("b");
console.log(stringList.get(0)); // 输出 a
泛型接口示例
interface Item<T> {
value: T;
toString(): string;
}
class NumberItem implements Item<number> {
value: number;
constructor(value: number) {
this.value = value;
}
toString() {
return this.value.toString();
}
}
let numberItem: Item<number> = new NumberItem(42);
console.log(numberItem.toString()); // 输出 42
高级类型特性
联合类型与交叉类型
联合类型
联合类型是指变量可以赋值为多种类型中的一种。例如,一个变量可以是字符串或数字类型。
let value: number | string;
value = 42;
value = "Hello, TypeScript!";
console.log(value); // 输出 Hello, TypeScript!
交叉类型
交叉类型是指将两个或多个接口合并成一个新的接口。这可以用于组合多个接口的属性和方法。
interface Person {
name: string;
}
interface Employee {
id: number;
}
type PersonEmployee = Person & Employee;
let personEmployee: PersonEmployee = {
name: "Alice",
id: 123
};
console.log(personEmployee.name, personEmployee.id); // 输出 Alice 123
映射类型
映射类型是一种高级类型特性,可以用来创建新的类型。它通常用于为现有类型中的每个属性创建新的类型。
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface User {
id: number;
email: string;
}
let readonlyUser: Readonly<User> = {
id: 123,
email: "[email protected]"
};
// readonlyUser.id = 456; // 编译错误,因为 id 是只读属性
console.log(readonlyUser.id, readonlyUser.email); // 输出 123 [email protected]
条件类型
条件类型是基于类型条件创建新类型的机制。它们通常用于条件地推导类型。
type IsString<T> = T extends string ? true : false;
let isString1: IsString<string>; // 输出 true
let isString2: IsString<number>; // 输出 false
模块化编程
模块的基本概念
TypeScript 支持两种模块化编程的模式:CommonJS 和 ES 模块。这两种模式允许将代码组织成独立的模块,便于管理和维护。
导入与导出机制
在模块化编程中,需要使用 import
和 export
语句来组织代码。下面是一个简单的模块示例:
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
export function subtract(a: number, b: number): number {
return a - b;
}
// main.ts
import { add, subtract } from "./math";
console.log(add(10, 5)); // 输出 15
console.log(subtract(10, 5)); // 输出 5
ES 模块与 CommonJS 模块的区别
ES 模块使用 .js
或 .ts
文件扩展名,并使用 import
和 export
语句。CommonJS 模块使用 .js
文件扩展名,并使用 require
和 module.exports
。
// esModule.ts
export const message = "Hello, ES Module!";
// commonjsModule.ts
module.exports = {
message: "Hello, CommonJS Module!"
};
使用 ES 模块:
// mainES.ts
import { message } from "./esModule";
console.log(message); // 输出 Hello, ES Module!
使用 CommonJS 模块:
// mainCommonJS.ts
const { message } = require("./commonjsModule");
console.log(message); // 输出 Hello, CommonJS Module!
装饰器应用
装饰器的基本概念
装饰器是一种特殊的声明,可以附加到类声明、方法、访问器、属性或参数。装饰器通常用于元编程,如在运行时修改或增强代码。
下面是一个简单的装饰器示例:
function log(target: any, key: string) {
console.log(`Accessing ${key} property`);
}
class User {
@log
name: string = "Alice";
}
let user = new User();
console.log(user.name); // 输出 Accessing name property Alice
装饰器工厂
装饰器工厂允许传递参数来创建装饰器。这种方式使得装饰器更加灵活和可复用。
function log(message: string) {
return function (target: any, key: string) {
console.log(`${message} ${key} property`);
};
}
class User {
@log("Accessing")
name: string = "Alice";
}
let user = new User();
console.log(user.name); // 输出 Accessing name property Alice
常见装饰器类型
@ClassDecorator
用于类声明@MethodDecorator
用于方法声明@PropertyDecorator
用于属性声明@ParameterDecorator
用于参数声明
下面是一个更复杂的装饰器示例,包括类装饰器和方法装饰器:
function classDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
name: string = "DecoratedInstance";
};
}
function methodDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
descriptor.value = function(...args: any[]) {
console.log(`Calling ${key} with arguments`, args);
return descriptor.value.apply(this, args);
};
}
@classDecorator
class User {
@methodDecorator
getName() {
return this.name;
}
}
let user = new User();
console.log(user.getName()); // 输出 Calling getName with arguments []
代码组织与最佳实践
项目结构建议
推荐的 TypeScript 项目结构可以包括以下部分:
src/
├── models/
│ └── user.ts
├── services/
│ └── userService.ts
├── routes/
│ └── userRoutes.ts
├── utils/
│ └── helpers.ts
└── index.ts
示例代码
在 user.ts
中:
export class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
在 userService.ts
中:
import { User } from "../models/user";
export class UserService {
getUser(id: number): User {
// 实现获取用户逻辑
return new User("Alice", 20);
}
}
在 userRoutes.ts
中:
import { UserService } from "../services/userService";
export const getUserById = (req, res) => {
const userService = new UserService();
const user = userService.getUser(req.params.id);
res.json(user);
};
在 helpers.ts
中:
export function log(message: string) {
console.log(message);
}
在 index.ts
中:
import { getUserById } from "./routes/userRoutes";
// 启动应用
log("Application started");
类型推断与类型断言
类型推断允许 TypeScript 从代码推断类型,而类型断言则允许显式指定类型。
类型推断示例:
let num = 42; // 类型推断为 number
let message = "Hello, TypeScript!"; // 类型推断为 string
类型断言示例:
let anyVar = "Hello" as string; // 类型断言为 string
function getLength(value: any): number {
return (value as string).length;
}
console.log(getLength("Hello")); // 输出 5
更多类型推断与类型断言示例:
// 更多类型推断示例
let unknownVar = "Hello"; // 类型推断为 string
let unknownVar2 = 42; // 类型推断为 number
// 更多类型断言示例
let anyVar = "Hello" as string; // 类型断言为 string
let anyVar2 = 42 as number; // 类型断言为 number
function getLength(value: any): number | undefined {
return (value as string).length;
}
console.log(getLength("Hello")); // 输出 5
console.log(getLength(42)); // 输出 undefined
TypeScript 配置文件详解
TypeScript 配置文件 tsconfig.json
用于指定编译器选项,如输出目录、模块类型和类型检查器行为。
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}
"target": "ES6"
:编译到 ES6 语法"module": "commonjs"
:使用 CommonJS 模块"outDir": "./dist"
:输出目录"strict": true
:启用严格类型检查"esModuleInterop": true
:允许 CommonJS 和 ES 模块互操作"skipLibCheck": true
:跳过库文件的类型检查"forceConsistentCasingInFileNames": true
:强制文件名大小写一致
总结,通过以上内容,你可以深入了解 TypeScript 的高级特性和最佳实践。掌握这些知识将帮助你编写更高效、更安全的代码。推荐使用慕课网等平台进行更多深入学习。
共同學習,寫下你的評論
評論加載中...
作者其他優質文章