用户工具

站点工具


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.reduce1); 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 官方文档 - 基础类型 - TypeScript 官方文档 - 日常类型

1)
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
typescript/第三章基本类型.txt · 最后更改: 127.0.0.1