TypeScript类型系统核心速通:从基础到常用复合类型包装类

TypeScript类型系统核心速通:从基础到常用复合类型包装类

一、TS的8大基础类型(继承自JS)

TS完全继承了JS的类型设计,核心基础类型有8个,全部是小写字母 (首字母大写的Number/String等是JS内置对象,不是类型!):

类型 说明 示例
boolean 布尔值(true/false) const isOk: boolean = true
string 字符串 const name: string = "TS"
number 数字(整数/浮点数/十六进制) const age: number = 20
bigint 大整数(ES2020新增) const num: bigint = 123n
symbol 唯一标识值 const id: symbol = Symbol()
object 对象/数组/函数(狭义对象) const arr: object = [1,2]
undefined 未定义值 let x: undefined = undefined
null 空值 const y: null = null

关键注意点:

  1. undefined/null默认可以赋值给任何类型(比如let n: number = null不报错),但开启strictNullChecks编译选项后,只能赋值给自身/any/unknown(推荐开启);
  2. bigintnumber不兼容(const x: bigint = 123会报错);
  3. object类型不包含原始类型(字符串/数字等),只包含对象、数组、函数。
ts 复制代码
// tsconfig.json
开启:
{
  "compilerOptions": {
    "strictNullChecks": true
  }
}

// 示例
let n: number = null; // 会报错,提示 "Type 'null' is not assignable to type 'number'."
let m: number | null = null; // 正确,允许为 null

二、包装类与大小写类型的核心区别

最容易踩坑的点就是「大小写类型」(比如stringString),而这一切的根源是JS的包装对象机制,先搞懂包装对象,再看类型就一目了然。

1. 什么是JS的包装对象?

JS中booleanstringnumberbigintsymbol这5种原始类型的值,本身没有方法(比如字符串的charAt()),但调用方法时,JS会自动把原始值转为"包装对象",执行完再销毁:

javascript 复制代码
'hello'.charAt(1); // 实际执行:new String('hello').charAt(1) → 'e'

let num = 123;
console.log(num.toFixed(2)); // 实际执行:new Number(123).toFixed(2) → '123.00'


let bool = true;
console.log(bool.toString()); // 实际执行:new Boolean(true).toString() → 'true'

其中:

  • symbol/bigint:无法通过new直接创建包装对象(new Symbol()会报错);
  • string/number/boolean:可以通过new创建包装对象(new String('hi'))。

2. TS中大小写类型的核心差异

TS为了区分"原始值"和"包装对象",给5种原始类型分别设计了小写(仅原始值)大写(包含包装对象) 两种类型:

类型对 范围说明 使用建议
string/String string:仅字符串原始值;String:原始值+包装对象 只用string
number/Number number:仅数字原始值;Number:原始值+包装对象 只用number
boolean/Boolean boolean:仅布尔原始值;Boolean:原始值+包装对象 只用boolean
bigint/BigInt 无实际差异(因无法创建包装对象) 只用bigint
symbol/Symbol 无实际差异(因无法创建包装对象) 只用symbol
代码示例:
typescript 复制代码
// 1. string(小写):只接受原始值,拒绝包装对象
const s1: string = "hello"; //  正确(原始值)
const s2: string = new String("hello"); //  报错(包装对象)

// 2. String(大写):接受原始值+包装对象(但完全没必要用)
const s3: String = "hello"; //  正确
const s4: String = new String("hello"); //  正确

// 3. 案例:内置方法只认小写类型
const n1: number = 1;
const n2: Number = 1;
Math.abs(n1); //  正确(Math.abs参数是number)
Math.abs(n2); //  报错(不接受Number类型)

3. Object vs object(对象类型的大小写)

在 TypeScript 中,Object(大写)和 object(小写)有着明确的区别,这两者的核心差异在于它们所包含的值的范围。

1. Object(大写)

  • 范围说明Object 是指 JavaScript 中所有对象的构造函数,并且在 TypeScript 中,它几乎包括所有类型的值,除了 undefinednull。这意味着变量可以被赋值为任何非空值,包括基本数据类型(如数字、字符串、布尔值)和对象(如数组、函数)。

    示例:

    typescript 复制代码
    let x: Object;
    x = 123;       // 允许
    x = 'hi';     // 允许
    x = [];       // 允许
    x = {};       // 允许
  • 使用建议 :尽管 Object 可以被用来表示几乎所有的值,但因为这个类型的范围过于宽泛,且它并没有提供类型检查的能力,所以 绝对不建议使用 Object 类型。使用它会导致类型安全性降低,容易在代码中引入潜在的错误或不确定性。

2. object(小写)

  • 范围说明object 是一个更为狭义的类型,仅表示一组"对象"。它仅包含普通的对象、数组和函数,不包括基本的原始值(如数字、字符串、布尔值等)。

    示例:

    typescript 复制代码
    let y: object;
    y = {};       // 允许(普通对象)
    y = [];      // 允许(数组)
    y = function() {}; // 允许(函数)
    y = 123;     // 错误(原始值)
    y = 'hi';    // 错误(原始值)
    y = null;    // 错误(null 不算对象)
  • 使用建议 :当你需要一个变量或参数的类型必须是一个对象时,你应该使用 object 类型。这种类型约束允许更好的类型检查,能够有效防止不必要的运行时错误。

小结

类型 范围说明 使用建议
Object(大写) 几乎包含所有值(除了 undefinednull),包括所有基本数据类型和对象。 绝对不要使用
object(小写) 仅包含普通对象、数组和函数,不包含原始值。 日常对象约束使用

理解重点

  • Object 的范围过于宽泛,难以进行有效的类型检查,使用时容易出现漏洞。
  • object 则是专门用于指出仅允许为对象的类型,可以在多个用例中提供更好的类型安全性和代码的可维护性。

三、常用复合类型:联合类型 & 交叉类型

1. 联合类型(|):"或"逻辑

|分隔多个类型,表示值可以是其中任意一种,核心是"多选一"。

核心用法:
typescript 复制代码
// 用法1:支持多类型入参
let id: string | number;
id = "1001"; //  正确(字符串)
id = 1001; //  正确(数字)

// 用法2:限定固定取值(枚举式约束,超实用)
type Gender = "male" | "female"; // 只能是这两个字符串
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"; // 接口请求方法
type Status = "success" | "error" | "pending"; // 接口状态

// 用法3:兼容null/undefined(开启strictNullChecks后)
let userName: string | null; // 可以是字符串或null
userName = "张三"; //  正确
userName = null; //  正确

使用联合类型时,TS无法确定具体类型,需通过"类型守卫"

typescript 复制代码
function printId(id: string | number) {
  // 类型守卫:判断是否为字符串
  if (typeof id === "string") {
    console.log(id.toUpperCase()); //  此时id是字符串
  } else {
    console.log(id); //  此时id是数字
  }
}

2. 交叉类型(&):"且"逻辑

&分隔多个类型,表示值必须同时满足所有类型,核心是"全满足",主要用于组合对象类型。

核心用法:
typescript 复制代码
// 用法1:组合多个对象类型
type User = { name: string; age: number };
type Contact = { phone: string; email: string };
// 交叉类型:同时拥有User和Contact的所有属性
type UserWithContact = User & Contact;

const user: UserWithContact = {
  name: "张三",
  age: 25,
  phone: "13800138000",
  email: "zhangsan@example.com" //  必须包含所有属性
};

// 用法2:为已有类型新增属性
type BaseOrder = { orderId: string; amount: number };
// 新增折扣属性
type DiscountOrder = BaseOrder & { discount: number; total: number };
注意点:

如果交叉类型包含"同名不同类型"的属性,该属性会变成never(无法赋值):

typescript 复制代码
type A = { age: number };
type B = { age: string };
type C = A & B;
// const c: C = { age: 18 }; //  报错(age类型为never)

四、提升效率的实用小技巧

1. type命令:给类型起别名

type定义类型别名,简化复杂类型,提升代码可读性:

typescript 复制代码
// 基础用法:简化基础类型
type Age = number;
let myAge: Age = 25;

// 实用用法:简化联合/交叉类型
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type PlainObject = Record<string, unknown>; // 约束仅普通对象

2. typeof运算符:提取变量的类型

TS扩展了typeof,可以"自动提取变量的类型",不用手动写:

typescript 复制代码
const obj = { name: "TS", version: 5.0 };
// 自动提取obj的类型:{ name: string; version: number }
type ObjType = typeof obj;

// 直接使用提取的类型
let newObj: ObjType = { name: "JS", version: 6.0 }; //  符合类型

五、核心总结

  1. TS基础类型共8个(全小写),undefined/null开启strictNullChecks更安全;
  2. 包装类是JS的底层机制,TS用"小写类型(仅原始值)"和"大写类型(含包装对象)"区分,只用小写类型
  3. 对象类型只选object(小写),Object(大写)范围过宽无意义;
  4. 联合类型(|)是"或"逻辑(多选一),交叉类型(&)是"且"逻辑(全满足);
  5. type别名简化复杂类型,typeof提取变量类型,提升开发效率。
相关推荐
Misnice1 天前
Webpack、Vite 、Rsbuild 区别
前端·webpack·node.js
小白学大数据1 天前
百科词条结构化抓取:Java 正则表达式与 XPath 解析对比
java·开发语言·爬虫·正则表达式
Kagol1 天前
🎉历时1年,TinyEditor v4.0 正式发布!
前端·typescript·开源
丶一派胡言丶1 天前
02-VUE介绍和指令
前端·javascript·vue.js
C_心欲无痕1 天前
网络相关 - 跨域解决方式
前端·网络
天蓝色的鱼鱼1 天前
Vue开发必考:defineComponent与defineAsyncComponent,你真的掌握吗?
前端·vue.js
用户81274828151201 天前
aosp14分屏分割线区域部分深入剖析-framework实战干货
前端
三小河1 天前
内网环境下 Web 离线地图的实现方案与合规性探讨
前端
2501_941807261 天前
在迪拜智能机场场景中构建行李实时调度与高并发航班数据分析平台的工程设计实践经验分享
java·前端·数据库