跳至内容
张叶安的小站
用户工具
登录
站点工具
搜索
工具
显示页面
过去修订
反向链接
最近更改
媒体管理器
网站地图
登录
>
最近更改
媒体管理器
网站地图
您的足迹:
typescript:第三章基本类型
本页面只读。您可以查看源文件,但不能更改它。如果您觉得这是系统错误,请联系管理员。
====== 第三章:基本类型 ====== ===== 本章概述 ===== TypeScript 拥有丰富的类型系统,本章将深入讲解基本数据类型,包括原始类型、数组、元组等。理解这些基础类型是掌握 TypeScript 类型系统的关键。 ===== 3.1 原始类型(Primitive Types) ===== ==== 3.1.1 boolean 布尔类型 ==== 布尔类型只有两种值:true 和 false。 ```typescript let isDone: boolean = false; let isActive: boolean = true; let hasPermission: boolean = true; // 通过表达式赋值 let isGreater: boolean = 5 > 3; // true let isEqual: boolean = "hello" === "world"; // false // 布尔对象(不推荐) let boolObject: Boolean = new Boolean(true); // 包装对象 let boolPrimitive: boolean = true; // 原始类型,推荐 ``` ==== 3.1.2 number 数字类型 ==== TypeScript 中所有数字都是浮点数,支持十进制、十六进制、二进制和八进制字面量。 ```typescript // 十进制 let decimal: number = 42; let float: number = 3.14159; let negative: number = -10; // 十六进制 let hex: number = 0xff; // 255 let hex2: number = 0xABC; // 2748 // 二进制 let binary: number = 0b1010; // 10 let binary2: number = 0b11110000; // 八进制 let octal: number = 0o744; // 484 // 特殊数值 let infinity: number = Infinity; let notANumber: number = NaN; // 科学计数法 let scientific: number = 1.5e10; // 15000000000 let small: number = 1.5e-10; // 下划线分隔符(ES2021+) let million: number = 1_000_000; let binaryWithSep: number = 0b1111_0000; ``` ==== 3.1.3 string 字符串类型 ==== ```typescript // 单引号 let singleQuote: string = 'Hello'; // 双引号 let doubleQuote: string = "World"; // 模板字符串(推荐) let name: string = "Alice"; let greeting: string = `Hello, ${name}!`; let multiLine: string = ` This is a multi-line string `; // 模板字符串支持表达式 let a: number = 5; let b: number = 10; let result: string = `The sum is ${a + b}`; // 字符串方法 let str: string = "TypeScript"; let upper: string = str.toUpperCase(); // "TYPESCRIPT" let lower: string = str.toLowerCase(); // "typescript" let length: number = str.length; // 10 let substring: string = str.substring(0, 4); // "Type" let includes: boolean = str.includes("Script"); // true ``` ==== 3.1.4 symbol 符号类型 ==== Symbol 是 ES6 引入的原始数据类型,表示唯一的标识符。 ```typescript // 创建 Symbol const sym1: symbol = Symbol(); const sym2: symbol = Symbol("description"); const sym3: symbol = Symbol("description"); // 每个 Symbol 都是唯一的 console.log(sym2 === sym3); // false // 作为对象属性键 const id: symbol = Symbol("id"); const user = { [id]: 12345, name: "Alice" }; // 获取 Symbol 属性需要使用 Object.getOwnPropertySymbols console.log(Object.getOwnPropertySymbols(user)); // [Symbol(id)] // Well-known Symbols const iterator: symbol = Symbol.iterator; const asyncIterator: symbol = Symbol.asyncIterator; const hasInstance: symbol = Symbol.hasInstance; ``` ==== 3.1.5 bigint 大整数类型 ==== BigInt 用于表示任意精度的整数,适合处理超出 number 安全整数范围的数值。 ```typescript // 创建 BigInt const big1: bigint = 9007199254740991n; const big2: bigint = BigInt(9007199254740991); const big3: bigint = BigInt("900719925474099199999"); // 运算 const sum: bigint = big1 + big2; const product: bigint = big1 * 2n; const power: bigint = 2n ** 100n; // 比较 const isEqual: boolean = big1 === big2; const isGreater: boolean = big1 > 0n; // 注意:BigInt 和 number 不能直接混合运算 // const invalid = big1 + 5; // Error const valid = big1 + 5n; // OK // 转换 const numFromBig: number = Number(big1); // 可能丢失精度 const strFromBig: string = big1.toString(); ``` ===== 3.2 特殊类型 ===== ==== 3.2.1 any 任意类型 ==== any 是最灵活的类型,可以赋值为任何类型,绕过类型检查。 ```typescript let notSure: any = 4; notSure = "maybe a string instead"; notSure = false; notSure = { name: "Alice" }; notSure = [1, 2, 3]; // 可以访问任何属性 notSure.ifItExists(); notSure.toFixed(); // 隐式 any // 在 noImplicitAny 关闭时,未注解的变量默认为 any function log(message) { // 参数类型隐式为 any console.log(message); } // 明确的 any 使用场景 // 1. 第三方库没有类型定义 let thirdPartyData: any = fetchLegacyData(); // 2. 动态内容 let dynamicContent: any = JSON.parse(jsonString); // 3. 逐步迁移项目 // 可以先用 any,再逐步添加类型 ``` ==== 3.2.2 unknown 未知类型 ==== unknown 是类型安全的 any,使用前必须进行类型检查。 ```typescript let notSure: unknown = 4; notSure = "hello"; notSure = true; // 不能直接使用 // notSure.toFixed(); // Error: Object is of type 'unknown' // 必须使用类型检查 if (typeof notSure === "number") { console.log(notSure.toFixed(2)); // OK } if (typeof notSure === "string") { console.log(notSure.toUpperCase()); // OK } // 类型断言 const value: unknown = "hello"; const str: string = value as string; // 使用类型守卫函数 function isString(value: unknown): value is string { return typeof value === "string"; } if (isString(notSure)) { console.log(notSure.length); // OK,TypeScript 知道是 string } ``` ==== 3.2.3 never 永不类型 ==== never 表示永远不会发生的值,用于: - 抛出异常的函数 - 无限循环的函数 - exhaustive type checking ```typescript // 抛出错误的函数返回 never function throwError(message: string): never { throw new Error(message); } // 无限循环 function infiniteLoop(): never { while (true) { console.log("Looping..."); } } // exhaustive checking function assertNever(x: never): never { throw new Error("Unexpected object: " + x); } type Shape = | { kind: "circle"; radius: number } | { kind: "square"; side: number } | { kind: "triangle"; base: number; height: number }; function getArea(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side ** 2; case "triangle": return (shape.base * shape.height) / 2; default: return assertNever(shape); // 如果 Shape 新增类型,这里会报错 } } ``` ==== 3.2.4 void 空类型 ==== void 表示没有返回值,通常用于函数。 ```typescript // 无返回值的函数 function logMessage(message: string): void { console.log(message); } function processData(data: unknown): void { // 处理数据,不返回结果 saveToDatabase(data); } // void 类型的变量只能赋值 undefined 或 null let unusable: void = undefined; // unusable = null; // 在 strictNullChecks 下可能报错 // 实际上 void 类型的变量很少使用 ``` ==== 3.2.5 null 和 undefined ==== ```typescript // undefined let u: undefined = undefined; // null let n: null = null; // strictNullChecks 开启时的区别 let str: string = "hello"; // str = null; // Error // str = undefined; // Error let nullableStr: string | null = null; // OK nullableStr = "hello"; // OK let optionalStr: string | undefined = undefined; // OK optionalStr = "hello"; // OK // 非空断言(谨慎使用) function getLength(str: string | null): number { return str!.length; // ! 告诉 TypeScript str 不为 null } // 更安全的做法 function getLengthSafe(str: string | null): number { return str ? str.length : 0; } ``` ===== 3.3 数组类型(Array Types) ===== ==== 3.3.1 数组类型注解 ==== ```typescript // 类型[] 语法 let numbers: number[] = [1, 2, 3, 4, 5]; let strings: string[] = ["a", "b", "c"]; let booleans: boolean[] = [true, false, true]; // Array<类型> 语法(泛型) let numbers2: Array<number> = [1, 2, 3]; let strings2: Array<string> = ["a", "b", "c"]; // 混合类型数组(不推荐) let mixed: (string | number)[] = ["a", 1, "b", 2]; // 对象数组 interface User { id: number; name: string; } let users: User[] = [ { id: 1, name: "Alice" }, { id: 2, name: "Bob" } ]; // 多维数组 let matrix: number[][] = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; let threeDArray: number[][][] = [[[1, 2]], [[3, 4]]]; ``` ==== 3.3.2 数组方法类型 ==== ```typescript const numbers: number[] = [1, 2, 3, 4, 5]; // 不改变原数组的方法 const doubled: number[] = numbers.map(n => n * 2); const evens: number[] = numbers.filter(n => n % 2 === 0); const sum: number = numbers.reduce((a, b) => a + b, 0); const found: number | undefined = numbers.find(n => n > 3); const hasEven: boolean = numbers.some(n => n % 2 === 0); const allPositive: boolean = numbers.every(n => n > 0); const index: number = numbers.findIndex(n => n === 3); const sliced: number[] = numbers.slice(1, 3); // 改变原数组的方法 const arr: number[] = [1, 2, 3]; arr.push(4); // 添加元素到末尾 arr.pop(); // 移除末尾元素 arr.unshift(0); // 添加元素到开头 arr.shift(); // 移除开头元素 arr.splice(1, 1); // 删除/插入元素 arr.sort((a, b) => b - a); // 排序 arr.reverse(); // 反转 ``` ==== 3.3.3 只读数组 ==== ```typescript // 使用 readonly 修饰符 const readonlyNumbers: readonly number[] = [1, 2, 3]; // readonlyNumbers.push(4); // Error // readonlyNumbers[0] = 0; // Error // 使用 ReadonlyArray 泛型 const readonlyStrings: ReadonlyArray<string> = ["a", "b"]; // 使用 Readonly 工具类型 interface Config { settings: Readonly<number[]>; } // 只读数组可以赋值给普通数组 const arr: readonly number[] = [1, 2, 3]; // const mutable: number[] = arr; // Error // 普通数组可以赋值给只读数组 const mutable: number[] = [1, 2, 3]; const readonly2: readonly number[] = mutable; // OK ``` ==== 3.3.4 数组类型推断 ==== ```typescript // 自动推断 const numbers = [1, 2, 3]; // number[] const strings = ["a", "b"]; // string[] const mixed = [1, "a", true]; // (string | number | boolean)[] // 空数组推断为 any[] const empty = []; // any[] // 应该显式声明类型 const emptyNumbers: number[] = []; // 使用 as const 得到字面量类型 const tuple = [1, 2, 3] as const; // readonly [1, 2, 3] const config = { ports: [3000, 8080] as const }; ``` ===== 3.4 元组类型(Tuple Types) ===== ==== 3.4.1 基本元组 ==== 元组是固定长度、固定类型的数组。 ```typescript // 定义元组 let person: [string, number] = ["Alice", 25]; // 顺序必须匹配 // let wrong: [string, number] = [25, "Alice"]; // Error // 长度必须匹配 // person.push("extra"); // 可以编译,但类型系统不限制 // person[2]; // Error: Tuple type '[string, number]' of length '2' has no element at index '2' // 可选元素 let optionalTuple: [string, number?] = ["Alice"]; optionalTuple = ["Alice", 25]; // OK // 剩余元素 let restTuple: [string, ...number[]] = ["scores", 85, 90, 95]; ``` ==== 3.4.2 命名元组 ==== ```typescript // 使用类型别名 type Point = [x: number, y: number]; const point: Point = [10, 20]; // 或使用接口(更推荐) interface Point2 { x: number; y: number; } const point2: Point2 = { x: 10, y: 20 }; // 具名元组元素(TypeScript 4.0+) type RGB = [red: number, green: number, blue: number]; const color: RGB = [255, 128, 0]; ``` ==== 3.4.3 元组与解构 ==== ```typescript // 元组解构 const point: [number, number] = [10, 20]; const [x, y] = point; // 函数返回元组 function getUserInfo(): [string, number] { return ["Alice", 25]; } const [name, age] = getUserInfo(); // 交换变量 let a = 1, b = 2; [a, b] = [b, a]; // 忽略元素 const [first, , third] = [1, 2, 3]; ``` ==== 3.4.4 只读元组 ==== ```typescript // 只读元组 const readonlyTuple: readonly [string, number] = ["Alice", 25]; // readonlyTuple[0] = "Bob"; // Error // 使用 Readonly 工具类型 type ReadonlyPoint = Readonly<[number, number]>; ``` ===== 3.5 枚举类型(Enum)补充 ===== 枚举在第四章会详细介绍,这里简单了解其作为基本类型的特性。 ```typescript // 数字枚举 enum Direction { Up, // 0 Down, // 1 Left, // 2 Right // 3 } // 字符串枚举 enum Color { Red = "RED", Green = "GREEN", Blue = "BLUE" } // 使用 const dir: Direction = Direction.Up; const color: Color = Color.Red; // 常量枚举(编译时内联) const enum Status { Active = 1, Inactive = 0 } ``` ===== 3.6 类型推断与注解的选择 ===== ==== 3.6.1 何时添加类型注解 ==== ```typescript // ✓ 函数参数和返回值 function calculate(x: number, y: number): number { return x + y; } // ✓ 对象属性 interface User { name: string; age: number; } // ✓ 复杂类型 const config: { apiUrl: string; timeout: number } = { apiUrl: "https://api.example.com", timeout: 5000 }; // ✓ 空数组 const numbers: number[] = []; // ✓ 类属性 class Person { name: string; age: number; } ``` ==== 3.6.2 何时依赖类型推断 ==== ```typescript // ✓ 简单变量初始化 const name = "Alice"; // string const age = 25; // number const isActive = true; // boolean // ✓ 从函数返回值推断 const result = calculate(1, 2); // number // ✓ 数组字面量 const colors = ["red", "green", "blue"]; // string[] // ✓ 对象字面量(简单情况) const point = { x: 0, y: 0 }; // { x: number; y: number } ``` ===== 3.7 类型兼容性 ===== ==== 3.7.1 原始类型兼容性 ==== ```typescript // 子类型可以赋值给父类型 let num: number = 10; let biggerNum: 10 = 10; num = biggerNum; // OK // biggerNum = num; // Error // 字面量类型 let exact: "hello" = "hello"; let general: string = exact; // OK // exact = general; // Error ``` ==== 3.7.2 数组和元组兼容性 ==== ```typescript // 元组是数组的子类型 const tuple: [string, number] = ["a", 1]; const arr: (string | number)[] = tuple; // OK // 长度不兼容 // const tuple2: [string, number] = arr; // Error // 数组协变 let strings: string[] = ["a", "b"]; let objects: object[] = strings; // OK(协变) ``` ===== 3.8 实用技巧 ===== ==== 3.8.1 类型别名 ==== ```typescript // 为复杂类型创建别名 type Point = [number, number]; type Point3D = [number, number, number]; type StringOrNumber = string | number; type ID = string | number; type Callback = (error: Error | null, result?: string) => void; ``` ==== 3.8.2 常量断言 ==== ```typescript // 使用 as const 创建只读字面量类型 const config = { host: "localhost", port: 3000, debug: true } as const; // config.port = 8080; // Error: Cannot assign to 'port' // 数组常量断言 const roles = ["admin", "user", "guest"] as const; type Role = typeof roles[number]; // "admin" | "user" | "guest" ``` ===== 3.9 本章小结 ===== 本章我们学习了: 1. **原始类型** - boolean、number、string、symbol、bigint 2. **特殊类型** - any、unknown、never、void、null、undefined 3. **数组类型** - 声明方式、方法、只读数组 4. **元组类型** - 固定长度数组、命名元组 5. **类型选择** - 何时添加类型注解,何时依赖推断 ===== 3.10 练习题 ===== ==== 练习 1:类型推断 ==== 分析以下代码中变量的推断类型: ```typescript const a = 42; const b = "hello"; const c = [1, 2, 3]; const d = [1, "two", true]; const e = null; const f = undefined; const g = { x: 10, y: 20 }; const h = [1, 2] as const; ``` <details> <summary>参考答案</summary> ```typescript const a: number = 42; const b: string = "hello"; const c: number[] = [1, 2, 3]; const d: (string | number | boolean)[] = [1, "two", true]; const e: null = null; const f: undefined = undefined; const g: { x: number; y: number } = { x: 10, y: 20 }; const h: readonly [1, 2] = [1, 2] as const; ``` </details> ==== 练习 2:数组操作 ==== 完成以下数组操作函数的类型定义和实现: ```typescript // 1. 过滤出数组中的偶数 function filterEven(numbers: number[]): number[] { // 实现 } // 2. 计算数组中所有数字的和 function sumArray(numbers: number[]): number { // 实现 } // 3. 将字符串数组转换为大写 function toUpperCaseArray(strings: string[]): string[] { // 实现 } // 4. 找出一个数字数组中的最大值和最小值,返回元组 function findMinMax(numbers: number[]): [number, number] { // 实现 } ``` <details> <summary>参考答案</summary> ```typescript // 1. 过滤偶数 function filterEven(numbers: number[]): number[] { return numbers.filter(n => n % 2 === 0); } // 2. 计算总和 function sumArray(numbers: number[]): number { return numbers.reduce((sum, n) => sum + n, 0); } // 3. 转换大写 function toUpperCaseArray(strings: string[]): string[] { return strings.map(s => s.toUpperCase()); } // 4. 找最大最小值 function findMinMax(numbers: number[]): [number, number] { if (numbers.length === 0) { throw new Error("Array is empty"); } let min = numbers[0]; let max = numbers[0]; for (const n of numbers) { if (n < min) min = n; if (n > max) max = n; } return [min, max]; } // 或使用内置方法 function findMinMax2(numbers: number[]): [number, number] { return [Math.min(...numbers), Math.max(...numbers)]; } ``` </details> ==== 练习 3:类型安全的数据处理 ==== 实现一个类型安全的 parseValue 函数: ```typescript type ParsedValue = string | number | boolean | null; function parseValue(input: unknown): ParsedValue { // 实现:根据 input 的实际类型返回相应的值 // - 如果是 string,直接返回 // - 如果是 number,直接返回 // - 如果是 boolean,直接返回 // - 如果是 null 或 undefined,返回 null // - 如果是其他类型,返回 null } ``` <details> <summary>参考答案</summary> ```typescript type ParsedValue = string | number | boolean | null; function parseValue(input: unknown): ParsedValue { if (typeof input === "string") { return input; } if (typeof input === "number") { return input; } if (typeof input === "boolean") { return input; } if (input === null || input === undefined) { return null; } return null; } // 测试 console.log(parseValue("hello")); // "hello" console.log(parseValue(42)); // 42 console.log(parseValue(true)); // true console.log(parseValue(null)); // null console.log(parseValue(undefined)); // null console.log(parseValue({})); // null ``` </details> ==== 练习 4:元组与对象转换 ==== 实现以下类型转换函数: ```typescript interface Point { x: number; y: number; } // 1. 将 Point 对象转换为元组 [x, y] function pointToTuple(point: Point): [number, number] { // 实现 } // 2. 将元组 [x, y] 转换为 Point 对象 function tupleToPoint(tuple: [number, number]): Point { // 实现 } // 3. 交换元组中的两个元素 function swap<T, U>(tuple: [T, U]): [U, T] { // 实现 } ``` <details> <summary>参考答案</summary> ```typescript interface Point { x: number; y: number; } // 1. 对象转元组 function pointToTuple(point: Point): [number, number] { return [point.x, point.y]; } // 2. 元组转对象 function tupleToPoint(tuple: [number, number]): Point { const [x, y] = tuple; return { x, y }; } // 3. 交换元组元素 function swap<T, U>(tuple: [T, U]): [U, T] { const [first, second] = tuple; return [second, first]; } // 测试 const point: Point = { x: 10, y: 20 }; const tuple = pointToTuple(point); // [10, 20] const backToPoint = tupleToPoint(tuple); // { x: 10, y: 20 } const swapped = swap(["hello", 42]); // [42, "hello"] ``` </details> ===== 扩展阅读 ===== - [[TypeScript:第四章_枚举与字面量类型|下一章:枚举与字面量类型]] - [[https://www.typescriptlang.org/docs/handbook/basic-types.html|TypeScript 官方文档 - 基础类型]] - [[https://www.typescriptlang.org/docs/handbook/2/everyday-types.html|TypeScript 官方文档 - 日常类型]]
typescript/第三章基本类型.txt
· 最后更改:
2026/02/03 19:45
由
127.0.0.1
页面工具
显示页面
过去修订
反向链接
回到顶部