2.1 TypeScript类型概述
2.1.1 静态类型 vs 动态类型
JavaScript的动态类型
// JavaScript - 动态类型
let value = 42; // number
value = "hello"; // string
value = true; // boolean
value = { name: "Alice" }; // object
// 运行时才能发现类型错误
function add(a, b) {
return a + b;
}
console.log(add(1, 2)); // 3
console.log(add(1, "2")); // "12" - 可能不是预期结果
TypeScript的静态类型
// TypeScript - 静态类型
let value: number = 42;
value = "hello"; // 编译错误:Type 'string' is not assignable to type 'number'
function add(a: number, b: number): number {
return a + b;
}
console.log(add(1, 2)); // 3
console.log(add(1, "2")); // 编译错误:Argument of type 'string' is not assignable to parameter of type 'number'
2.1.2 类型注解和类型推断
类型注解(Type Annotations)
// 显式类型注解
let name: string = "Alice";
let age: number = 30;
let isActive: boolean = true;
// 函数参数和返回值类型注解
function greet(name: string): string {
return `Hello, ${name}!`;
}
// 对象类型注解
let person: { name: string; age: number } = {
name: "Bob",
age: 25
};
类型推断(Type Inference)
// TypeScript自动推断类型
let name = "Alice"; // 推断为 string
let age = 30; // 推断为 number
let isActive = true; // 推断为 boolean
// 函数返回值类型推断
function add(a: number, b: number) {
return a + b; // 推断返回类型为 number
}
// 数组类型推断
let numbers = [1, 2, 3]; // 推断为 number[]
let mixed = [1, "hello"]; // 推断为 (string | number)[]
2.2 基本类型
2.2.1 原始类型
number类型
// 数字类型
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: number = 1_000_000; // 数字分隔符
// 特殊数值
let notANumber: number = NaN;
let infinity: number = Infinity;
let negativeInfinity: number = -Infinity;
// 数学运算
function calculate(a: number, b: number): number {
return a * b + Math.PI;
}
// 数字验证函数
function isValidNumber(value: number): boolean {
return !isNaN(value) && isFinite(value);
}
string类型
// 字符串类型
let firstName: string = "John";
let lastName: string = 'Doe';
// 模板字符串
let fullName: string = `${firstName} ${lastName}`;
let greeting: string = `Hello, ${fullName}!
Welcome to TypeScript!`;
// 字符串方法
function formatName(name: string): string {
return name.trim().toLowerCase().replace(/\b\w/g, l => l.toUpperCase());
}
// 字符串字面量类型
type Theme = "light" | "dark";
let currentTheme: Theme = "light";
// 字符串操作示例
function processText(text: string): {
length: number;
words: number;
uppercase: string;
lowercase: string;
} {
return {
length: text.length,
words: text.split(/\s+/).length,
uppercase: text.toUpperCase(),
lowercase: text.toLowerCase()
};
}
boolean类型
// 布尔类型
let isCompleted: boolean = false;
let isValid: boolean = true;
// 布尔运算
function canAccess(isLoggedIn: boolean, hasPermission: boolean): boolean {
return isLoggedIn && hasPermission;
}
// 条件判断
function validateInput(input: string): boolean {
return input.length > 0 && input.trim() !== "";
}
// 布尔转换
function toBooleanSafe(value: any): boolean {
return Boolean(value);
}
2.2.2 特殊类型
null和undefined
// null和undefined类型
let nullValue: null = null;
let undefinedValue: undefined = undefined;
// 在严格模式下,null和undefined是不同的类型
let maybeString: string | null = null;
let maybeNumber: number | undefined = undefined;
// 可选属性
interface User {
name: string;
email?: string; // 等同于 email: string | undefined
}
function createUser(name: string, email?: string): User {
return {
name,
...(email && { email })
};
}
// 空值检查
function processValue(value: string | null | undefined): string {
if (value == null) { // 检查null和undefined
return "No value";
}
return value.toUpperCase();
}
// 非空断言操作符
function getLength(value: string | null): number {
return value!.length; // 断言value不为null
}
void类型
// void类型 - 表示没有返回值
function logMessage(message: string): void {
console.log(message);
// 没有return语句,或者return;
}
function processData(data: any[]): void {
data.forEach(item => {
console.log(item);
});
return; // 可以显式返回undefined
}
// void类型的变量只能赋值为undefined或null(在非严格模式下)
let unusable: void = undefined;
never类型
// never类型 - 表示永远不会有返回值
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {
// 无限循环
}
}
// never类型在联合类型中会被忽略
type StringOrNever = string | never; // 等同于 string
// 用于详尽性检查
function assertNever(x: never): never {
throw new Error("Unexpected object: " + x);
}
function processShape(shape: "circle" | "square"): number {
switch (shape) {
case "circle":
return Math.PI;
case "square":
return 4;
default:
return assertNever(shape); // 确保所有情况都被处理
}
}
any类型
// any类型 - 关闭类型检查
let anything: any = 42;
anything = "hello";
anything = true;
anything.foo.bar; // 不会有类型检查
// 应该避免使用any,但在某些情况下有用
function parseJSON(json: string): any {
return JSON.parse(json);
}
// 逐步迁移JavaScript代码时使用
let legacyData: any = getLegacyData();
// 更好的替代方案
function parseJSONSafe<T>(json: string): T {
return JSON.parse(json) as T;
}
// unknown类型是any的安全替代
let userInput: unknown = getUserInput();
// 使用unknown需要类型检查
if (typeof userInput === "string") {
console.log(userInput.toUpperCase());
}
2.3 数组和元组
2.3.1 数组类型
基本数组语法
// 数组类型声明的两种方式
let numbers1: number[] = [1, 2, 3, 4, 5];
let numbers2: Array<number> = [1, 2, 3, 4, 5];
let strings: string[] = ["apple", "banana", "orange"];
let booleans: boolean[] = [true, false, true];
// 多维数组
let matrix: number[][] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
// 混合类型数组
let mixed: (string | number)[] = [1, "hello", 2, "world"];
数组操作
// 数组方法的类型安全
const numbers: number[] = [1, 2, 3, 4, 5];
// map方法
const doubled: number[] = numbers.map(n => n * 2);
const strings: string[] = numbers.map(n => n.toString());
// filter方法
const evens: number[] = numbers.filter(n => n % 2 === 0);
// reduce方法
const sum: number = numbers.reduce((acc, curr) => acc + curr, 0);
// find方法
const found: number | undefined = numbers.find(n => n > 3);
// 数组解构
const [first, second, ...rest] = numbers;
console.log(first); // number
console.log(second); // number
console.log(rest); // number[]
只读数组
// 只读数组
const readonlyNumbers: readonly number[] = [1, 2, 3];
const readonlyNumbers2: ReadonlyArray<number> = [1, 2, 3];
// readonlyNumbers.push(4); // 错误:只读数组不能修改
// 函数参数使用只读数组
function processNumbers(numbers: readonly number[]): number {
return numbers.reduce((sum, num) => sum + num, 0);
}
// 数组工具函数
function getFirstElement<T>(arr: readonly T[]): T | undefined {
return arr[0];
}
function getLastElement<T>(arr: readonly T[]): T | undefined {
return arr[arr.length - 1];
}
2.3.2 元组类型
基本元组
// 元组类型 - 固定长度和类型的数组
let person: [string, number] = ["Alice", 30];
let coordinate: [number, number] = [10, 20];
// 访问元组元素
const name = person[0]; // string
const age = person[1]; // number
// 元组解构
const [personName, personAge] = person;
// 元组作为函数返回值
function getNameAndAge(): [string, number] {
return ["Bob", 25];
}
const [userName, userAge] = getNameAndAge();
可选元组元素
// 可选元组元素
type OptionalTuple = [string, number?];
let tuple1: OptionalTuple = ["hello"];
let tuple2: OptionalTuple = ["hello", 42];
// 剩余元素
type StringNumberBooleans = [string, number, ...boolean[]];
let example1: StringNumberBooleans = ["hello", 42];
let example2: StringNumberBooleans = ["hello", 42, true, false, true];
命名元组
// 命名元组(TypeScript 4.0+)
type Point = [x: number, y: number];
type Range = [start: number, end: number];
function calculateDistance(point1: Point, point2: Point): number {
const [x1, y1] = point1;
const [x2, y2] = point2;
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
// 函数返回命名元组
function parseCoordinate(input: string): [x: number, y: number] | null {
const match = input.match(/\((\d+),\s*(\d+)\)/);
if (match) {
return [parseInt(match[1]), parseInt(match[2])];
}
return null;
}
元组的实际应用
// 状态管理(类似React的useState)
type State<T> = [T, (newState: T) => void];
function createState<T>(initialValue: T): State<T> {
let value = initialValue;
const setValue = (newValue: T) => {
value = newValue;
};
return [value, setValue];
}
const [count, setCount] = createState(0);
// 数据库查询结果
type QueryResult<T> = [data: T[], error: string | null, loading: boolean];
function useQuery<T>(query: string): QueryResult<T> {
// 模拟查询逻辑
return [[], null, false];
}
const [users, error, loading] = useQuery<User>("SELECT * FROM users");
2.4 对象类型
2.4.1 对象类型注解
基本对象类型
// 对象类型注解
let person: {
name: string;
age: number;
email: string;
} = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
// 可选属性
let user: {
name: string;
age: number;
email?: string; // 可选属性
} = {
name: "Bob",
age: 25
// email可以省略
};
// 只读属性
let config: {
readonly apiUrl: string;
readonly timeout: number;
} = {
apiUrl: "https://api.example.com",
timeout: 5000
};
// config.apiUrl = "new url"; // 错误:只读属性不能修改
索引签名
// 索引签名 - 允许动态属性
interface StringDictionary {
[key: string]: string;
}
let dict: StringDictionary = {
name: "Alice",
city: "New York",
country: "USA"
};
// 数字索引签名
interface NumberArray {
[index: number]: number;
}
let numbers: NumberArray = [1, 2, 3, 4, 5];
// 混合索引签名
interface MixedObject {
name: string; // 固定属性
[key: string]: any; // 动态属性
}
let obj: MixedObject = {
name: "test",
age: 30,
active: true
};
嵌套对象
// 嵌套对象类型
interface Address {
street: string;
city: string;
zipCode: string;
country: string;
}
interface Person {
name: string;
age: number;
address: Address;
contacts: {
email: string;
phone?: string;
};
}
const person: Person = {
name: "Alice",
age: 30,
address: {
street: "123 Main St",
city: "New York",
zipCode: "10001",
country: "USA"
},
contacts: {
email: "alice@example.com",
phone: "+1-555-0123"
}
};
// 深度访问
function getPersonInfo(person: Person): string {
return `${person.name} lives in ${person.address.city}, ${person.address.country}`;
}
2.4.2 接口(Interface)
基本接口定义
// 接口定义
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
// 使用接口
function createUser(userData: User): User {
return {
...userData,
id: Date.now()
};
}
const newUser: User = {
id: 1,
name: "Alice",
email: "alice@example.com",
isActive: true
};
可选属性和只读属性
interface Product {
readonly id: number; // 只读属性
name: string;
price: number;
description?: string; // 可选属性
category?: string;
readonly createdAt: Date;
}
function createProduct(data: Omit<Product, 'id' | 'createdAt'>): Product {
return {
id: Math.random(),
createdAt: new Date(),
...data
};
}
const product = createProduct({
name: "Laptop",
price: 999.99,
description: "High-performance laptop"
});
// product.id = 123; // 错误:只读属性
函数类型接口
// 函数类型接口
interface SearchFunction {
(source: string, subString: string): boolean;
}
const mySearch: SearchFunction = function(source: string, subString: string): boolean {
return source.indexOf(subString) > -1;
};
// 或者使用箭头函数
const mySearch2: SearchFunction = (source, subString) => {
return source.includes(subString);
};
// 方法签名
interface Calculator {
add(a: number, b: number): number;
subtract(a: number, b: number): number;
multiply(a: number, b: number): number;
divide(a: number, b: number): number;
}
class BasicCalculator implements Calculator {
add(a: number, b: number): number {
return a + b;
}
subtract(a: number, b: number): number {
return a - b;
}
multiply(a: number, b: number): number {
return a * b;
}
divide(a: number, b: number): number {
if (b === 0) throw new Error("Division by zero");
return a / b;
}
}
接口继承
// 基础接口
interface Animal {
name: string;
age: number;
}
// 继承接口
interface Dog extends Animal {
breed: string;
bark(): void;
}
interface Cat extends Animal {
color: string;
meow(): void;
}
// 多重继承
interface Pet extends Animal {
owner: string;
}
interface ServiceDog extends Dog, Pet {
serviceType: string;
isWorking: boolean;
}
const serviceDog: ServiceDog = {
name: "Buddy",
age: 3,
breed: "Golden Retriever",
owner: "Alice",
serviceType: "Guide Dog",
isWorking: true,
bark() {
console.log("Woof!");
}
};
2.4.3 类型别名(Type Aliases)
基本类型别名
// 类型别名
type UserID = number;
type UserName = string;
type UserEmail = string;
// 使用类型别名
function getUserById(id: UserID): User | null {
// 实现逻辑
return null;
}
// 联合类型别名
type Status = "pending" | "approved" | "rejected";
type Theme = "light" | "dark" | "auto";
function setTheme(theme: Theme): void {
document.body.className = theme;
}
// 复杂类型别名
type EventHandler<T> = (event: T) => void;
type ApiResponse<T> = {
data: T;
status: number;
message: string;
};
接口 vs 类型别名
// 接口
interface UserInterface {
name: string;
age: number;
}
// 类型别名
type UserType = {
name: string;
age: number;
};
// 接口可以被扩展
interface UserInterface {
email: string; // 接口合并
}
// 类型别名不能被重新声明
// type UserType = { email: string; } // 错误
// 类型别名可以表示联合类型
type StringOrNumber = string | number;
// 接口不能表示联合类型
// interface StringOrNumber = string | number; // 错误
// 类型别名可以使用计算属性
type Keys = "name" | "age";
type UserRecord = {
[K in Keys]: string;
};
2.5 函数类型
2.5.1 函数类型注解
基本函数类型
// 函数声明
function add(a: number, b: number): number {
return a + b;
}
// 函数表达式
const multiply = function(a: number, b: number): number {
return a * b;
};
// 箭头函数
const divide = (a: number, b: number): number => {
if (b === 0) throw new Error("Division by zero");
return a / b;
};
// 完整的函数类型注解
const subtract: (a: number, b: number) => number = (a, b) => a - b;
可选参数和默认参数
// 可选参数
function greet(name: string, greeting?: string): string {
return `${greeting || "Hello"}, ${name}!`;
}
console.log(greet("Alice")); // "Hello, Alice!"
console.log(greet("Bob", "Hi")); // "Hi, Bob!"
// 默认参数
function createUser(name: string, age: number = 18, isActive: boolean = true): User {
return {
id: Math.random(),
name,
age,
isActive
};
}
// 剩余参数
function sum(...numbers: number[]): number {
return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// 混合参数
function logMessage(level: string, message: string, ...details: any[]): void {
console.log(`[${level}] ${message}`, ...details);
}
logMessage("INFO", "User logged in", { userId: 123, timestamp: new Date() });
函数重载
// 函数重载声明
function parseValue(value: string): string;
function parseValue(value: number): number;
function parseValue(value: boolean): boolean;
// 函数实现
function parseValue(value: string | number | boolean): string | number | boolean {
if (typeof value === "string") {
return value.trim();
} else if (typeof value === "number") {
return Math.round(value);
} else {
return value;
}
}
// 使用重载
const str = parseValue(" hello "); // string
const num = parseValue(3.14); // number
const bool = parseValue(true); // boolean
// 更复杂的重载示例
interface Contact {
name: string;
email?: string;
phone?: string;
}
function createContact(name: string): Contact;
function createContact(name: string, email: string): Contact;
function createContact(name: string, email: string, phone: string): Contact;
function createContact(name: string, email?: string, phone?: string): Contact {
const contact: Contact = { name };
if (email) contact.email = email;
if (phone) contact.phone = phone;
return contact;
}
2.5.2 高阶函数
函数作为参数
// 回调函数类型
type Callback<T> = (item: T) => void;
type Predicate<T> = (item: T) => boolean;
type Transformer<T, U> = (item: T) => U;
// 高阶函数示例
function forEach<T>(array: T[], callback: Callback<T>): void {
for (const item of array) {
callback(item);
}
}
function filter<T>(array: T[], predicate: Predicate<T>): T[] {
const result: T[] = [];
for (const item of array) {
if (predicate(item)) {
result.push(item);
}
}
return result;
}
function map<T, U>(array: T[], transformer: Transformer<T, U>): U[] {
const result: U[] = [];
for (const item of array) {
result.push(transformer(item));
}
return result;
}
// 使用示例
const numbers = [1, 2, 3, 4, 5];
forEach(numbers, num => console.log(num));
const evens = filter(numbers, num => num % 2 === 0);
const doubled = map(numbers, num => num * 2);
const strings = map(numbers, num => num.toString());
函数作为返回值
// 返回函数的函数
function createMultiplier(factor: number): (value: number) => number {
return (value: number) => value * factor;
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(4)); // 12
// 柯里化函数
function curry<T, U, V>(fn: (a: T, b: U) => V): (a: T) => (b: U) => V {
return (a: T) => (b: U) => fn(a, b);
}
const add = (a: number, b: number) => a + b;
const curriedAdd = curry(add);
const add5 = curriedAdd(5);
console.log(add5(3)); // 8
// 装饰器模式
function withLogging<T extends any[], U>(
fn: (...args: T) => U
): (...args: T) => U {
return (...args: T) => {
console.log(`Calling function with args:`, args);
const result = fn(...args);
console.log(`Function returned:`, result);
return result;
};
}
const loggedAdd = withLogging(add);
console.log(loggedAdd(2, 3)); // 带日志的加法
2.6 联合类型和交叉类型
2.6.1 联合类型(Union Types)
基本联合类型
// 联合类型
type StringOrNumber = string | number;
type Status = "loading" | "success" | "error";
function formatValue(value: StringOrNumber): string {
if (typeof value === "string") {
return value.toUpperCase();
} else {
return value.toString();
}
}
// 函数参数联合类型
function processId(id: string | number): string {
// 类型守卫
if (typeof id === "string") {
return id.toLowerCase();
} else {
return id.toString();
}
}
// 数组联合类型
type MixedArray = (string | number | boolean)[];
const mixed: MixedArray = ["hello", 42, true, "world", 3.14];
对象联合类型
// 不同形状的对象联合
interface Circle {
kind: "circle";
radius: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
interface Triangle {
kind: "triangle";
base: number;
height: number;
}
type Shape = Circle | Rectangle | Triangle;
// 使用判别联合
function calculateArea(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "rectangle":
return shape.width * shape.height;
case "triangle":
return (shape.base * shape.height) / 2;
default:
// 详尽性检查
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
联合类型的类型守卫
// 自定义类型守卫
function isString(value: unknown): value is string {
return typeof value === "string";
}
function isNumber(value: unknown): value is number {
return typeof value === "number";
}
function processValue(value: unknown): string {
if (isString(value)) {
return value.toUpperCase(); // TypeScript知道这里value是string
} else if (isNumber(value)) {
return value.toString(); // TypeScript知道这里value是number
} else {
return "Unknown type";
}
}
// in操作符类型守卫
function isCircle(shape: Shape): shape is Circle {
return "radius" in shape;
}
function isRectangle(shape: Shape): shape is Rectangle {
return "width" in shape && "height" in shape;
}
function getShapeInfo(shape: Shape): string {
if (isCircle(shape)) {
return `Circle with radius ${shape.radius}`;
} else if (isRectangle(shape)) {
return `Rectangle ${shape.width}x${shape.height}`;
} else {
return `Triangle with base ${shape.base} and height ${shape.height}`;
}
}
2.6.2 交叉类型(Intersection Types)
基本交叉类型
// 交叉类型 - 组合多个类型
interface Person {
name: string;
age: number;
}
interface Employee {
employeeId: number;
department: string;
}
type PersonEmployee = Person & Employee;
const employee: PersonEmployee = {
name: "Alice",
age: 30,
employeeId: 12345,
department: "Engineering"
};
// 函数参数交叉类型
function processEmployee(person: Person & Employee): string {
return `${person.name} (ID: ${person.employeeId}) works in ${person.department}`;
}
混合对象类型
// 混合多个接口
interface Timestamped {
timestamp: Date;
}
interface Tagged {
tags: string[];
}
type TimestampedTagged<T> = T & Timestamped & Tagged;
interface BlogPost {
title: string;
content: string;
author: string;
}
type EnhancedBlogPost = TimestampedTagged<BlogPost>;
const post: EnhancedBlogPost = {
title: "TypeScript Guide",
content: "Learning TypeScript...",
author: "Alice",
timestamp: new Date(),
tags: ["typescript", "programming", "tutorial"]
};
函数类型交叉
// 函数类型交叉
type Logger = {
log: (message: string) => void;
};
type Counter = {
count: number;
increment: () => void;
};
type LoggerCounter = Logger & Counter;
const loggerCounter: LoggerCounter = {
count: 0,
log(message: string) {
console.log(`[${this.count}] ${message}`);
},
increment() {
this.count++;
}
};
loggerCounter.log("Hello"); // [0] Hello
loggerCounter.increment();
loggerCounter.log("World"); // [1] World
2.7 类型断言和类型守卫
2.7.1 类型断言
基本类型断言
// 类型断言 - 告诉编译器变量的确切类型
let someValue: unknown = "this is a string";
// 角括号语法(在JSX中不可用)
let strLength1: number = (<string>someValue).length;
// as语法(推荐)
let strLength2: number = (someValue as string).length;
// DOM元素类型断言
const inputElement = document.getElementById("myInput") as HTMLInputElement;
inputElement.value = "Hello";
// 非空断言操作符
function processElement(element: HTMLElement | null) {
// 确信element不为null
element!.style.display = "none";
}
常量断言
// 常量断言
const colors = ["red", "green", "blue"] as const;
// colors的类型是 readonly ["red", "green", "blue"]
const config = {
apiUrl: "https://api.example.com",
timeout: 5000
} as const;
// config的类型是 { readonly apiUrl: "https://api.example.com"; readonly timeout: 5000; }
// 枚举替代
const Direction = {
Up: "UP",
Down: "DOWN",
Left: "LEFT",
Right: "RIGHT"
} as const;
type Direction = typeof Direction[keyof typeof Direction];
// Direction类型是 "UP" | "DOWN" | "LEFT" | "RIGHT"
2.7.2 类型守卫
内置类型守卫
// typeof类型守卫
function processValue(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
} else {
return value.toString();
}
}
// instanceof类型守卫
class Dog {
bark() {
console.log("Woof!");
}
}
class Cat {
meow() {
console.log("Meow!");
}
}
function makeSound(animal: Dog | Cat) {
if (animal instanceof Dog) {
animal.bark();
} else {
animal.meow();
}
}
// in操作符类型守卫
interface Fish {
swim(): void;
}
interface Bird {
fly(): void;
}
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal.swim();
} else {
animal.fly();
}
}
自定义类型守卫
// 自定义类型守卫函数
function isString(value: any): value is string {
return typeof value === "string";
}
function isNumber(value: any): value is number {
return typeof value === "number" && !isNaN(value);
}
function isArray<T>(value: any): value is T[] {
return Array.isArray(value);
}
// 复杂对象类型守卫
interface User {
id: number;
name: string;
email: string;
}
function isUser(obj: any): obj is User {
return obj &&
typeof obj.id === "number" &&
typeof obj.name === "string" &&
typeof obj.email === "string";
}
function processUserData(data: unknown) {
if (isUser(data)) {
// TypeScript现在知道data是User类型
console.log(`User: ${data.name} (${data.email})`);
} else {
console.log("Invalid user data");
}
}
// 泛型类型守卫
function isArrayOf<T>(value: any, guard: (item: any) => item is T): value is T[] {
return Array.isArray(value) && value.every(guard);
}
const data: unknown = [1, 2, 3, 4, 5];
if (isArrayOf(data, isNumber)) {
// data现在是number[]类型
const sum = data.reduce((a, b) => a + b, 0);
}
本章练习
练习1:基本类型
- 创建不同类型的变量并进行类型注解
- 实现一个函数,接受多种类型的参数
- 使用类型推断创建复杂的数据结构
练习2:数组和元组
- 创建不同类型的数组并实现操作函数
- 使用元组表示坐标点并实现距离计算
- 实现一个通用的数组工具库
练习3:对象和接口
- 设计用户管理系统的接口
- 实现接口继承和组合
- 创建灵活的配置对象类型
练习4:函数类型
- 实现函数重载
- 创建高阶函数
- 使用类型守卫处理联合类型
练习5:联合和交叉类型
- 设计状态管理系统
- 实现类型安全的事件系统
- 创建可扩展的插件架构
本章总结
在本章中,我们深入学习了TypeScript的基础类型系统:
- 基本类型:掌握了原始类型和特殊类型的使用
- 数组和元组:学会了集合类型的定义和操作
- 对象类型:理解了接口和类型别名的区别和应用
- 函数类型:掌握了函数签名和高阶函数的类型定义
- 联合和交叉类型:学会了复杂类型的组合和使用
- 类型断言和守卫:掌握了类型安全的编程技巧
下一章我们将学习TypeScript的接口和类,这是面向对象编程的核心概念。