TypeScript 中 Object(大写) 与 object(小写)???

TypeScript 中,Object(大写)和 object(小写)这对大小写兄弟,是不是一个穿西装打领带,一个穿T恤牛仔裤?它们到底有啥区别,还是说只是一个字母的大小写游戏?下面我们直接进入正题:


1. Object(大写)

  • 含义

    • Object 是 JavaScript 中的全局对象类型,表示所有对象的基类(包括原始类型的包装对象,如 StringNumberBoolean 等)。
    • 它包含了 JavaScript 中所有对象共有的属性和方法,例如 toStringhasOwnProperty 等。
  • 特点

    • 包括所有对象类型(包括原始类型的包装对象)。
    • 可以赋值给任何对象类型。
  • 示例

    typescript 复制代码
    const obj1: Object = { name: "Alice" }; // 普通对象
    const obj2: Object = new String("Hello"); // 字符串包装对象
    const obj3: Object = 42; // 合法,因为 42 会被装箱为 Number 对象

2. object(小写)

  • 含义

    • object 是 TypeScript 中的一种类型,表示非原始类型的对象(即不包括 stringnumberbooleansymbolnullundefined)。
    • 它仅表示普通的对象类型(如 {}{ key: value }、数组、函数等)。
  • 特点

    • 不包括原始类型及其包装对象。
    • 更严格,适合用于限制类型为普通对象。
  • 示例

    typescript 复制代码
    const obj1: object = { name: "Alice" }; // 普通对象
    const obj2: object = [1, 2, 3]; // 数组
    const obj3: object = () => {}; // 函数
    const obj4: object = new String("Hello"); // 合法,字符串包装对象
    const obj5: object = 42; // 报错,原始类型不能赋值给 object

3. 主要区别

特性 Object(大写) object(小写)
范围 包括所有对象类型(包括原始类型的包装对象) 仅包括非原始类型的对象
原始类型 可以赋值原始类型(会被装箱为对象) 不能赋值原始类型
严格性 较宽松 较严格
常见用途 较少使用,通常用于兼容旧代码 用于限制类型为普通对象

4. 使用场景

  • Object(大写)

    • 适用于需要兼容所有对象类型(包括原始类型的包装对象)的场景。
    • 由于它的范围较广,通常不建议在现代 TypeScript 代码中使用。
  • object(小写)

    • 适用于需要限制类型为普通对象的场景。
    • 更符合 TypeScript 的类型安全设计,推荐使用。

5. 注意事项

  • 避免使用 Object

    • Object 的范围太广,容易引入类型安全问题。例如,Object 可以接受原始类型,这可能会导致意外的行为。
  • 优先使用 object

    • object 更严格,能够更好地表达"普通对象"的意图。
  • 原始类型与对象类型

    • 原始类型(如 stringnumber)和它们的包装对象(如 StringNumber)是不同的类型。object 不包括原始类型,但包括它们的包装对象。

6. 示例对比

typescript 复制代码
// Object(大写)
const obj1: Object = { name: "Alice" }; // 合法
const obj2: Object = 42; // 合法,42 会被装箱为 Number 对象

// object(小写)
const obj3: object = { name: "Alice" }; // 合法
const obj4: object = 42; // 报错,原始类型不能赋值给 object

总结

  • Object(大写)是 JavaScript 的全局对象类型,范围较广,包括所有对象类型(甚至原始类型的包装对象)。
  • object(小写)是 TypeScript 中的一种类型,仅表示非原始类型的对象,更严格且更安全。
  • 在现代 TypeScript 开发中,推荐使用 object 而不是 Object,以更好地表达类型意图并提高代码的类型安全性。

???那当我们约束对象类型的时候,是 T extends Object 呢?还是 T extends object 呢?

1. extends object 的优势

  • 更严格

    • object 仅表示非原始类型的对象(如 {}{ key: value }、数组、函数等),不包括原始类型(如 stringnumberboolean 等)。
    • 这种约束更符合大多数场景的需求,避免意外传入原始类型。
  • 更符合 TypeScript 的设计理念

    • TypeScript 的类型系统旨在提供严格的类型检查,而 object 更符合这一目标。
  • 示例

    typescript 复制代码
    function printObject(obj: object) {
      console.log(obj);
    }
    printObject({ name: "Alice" }); // 合法
    printObject([1, 2, 3]); // 合法
    printObject(42); // 报错:原始类型不能赋值给 object

2. extends Object 的问题

  • 范围太广

    • Object 包括所有对象类型(包括原始类型的包装对象,如 StringNumber 等),甚至允许原始类型(如 stringnumber 等)被隐式装箱为对象。
    • 这种约束过于宽松,容易引入类型安全问题。
  • 示例

    typescript 复制代码
    function printObject(obj: Object) {
      console.log(obj);
    }
    printObject({ name: "Alice" }); // 合法
    printObject(42); // 合法,42 会被隐式装箱为 Number 对象
    printObject("Hello"); // 合法,"Hello" 会被隐式装箱为 String 对象

3. 为什么推荐 extends object

  • 更明确的类型约束

    • 使用 extends object 可以确保传入的值是一个真正的对象,而不是原始类型。
  • 避免隐式装箱

    • extends object 不会接受原始类型,因此不会触发 JavaScript 的隐式装箱行为。
  • 示例

    typescript 复制代码
    function processObject<T extends object>(obj: T) {
      console.log(obj);
    }
    processObject({ name: "Alice" }); // 合法
    processObject([1, 2, 3]); // 合法
    processObject(42); // 报错:原始类型不能赋值给 object

4. extends Object 的潜在问题

  • 隐式装箱

    • JavaScript 中的原始类型(如 stringnumber 等)在某些情况下会被隐式装箱为对象。例如,"hello".toUpperCase() 中的 "hello" 会被临时装箱为 String 对象。
    • 使用 extends Object 时,可能会意外接受原始类型,导致类型检查不够严格。
  • 类型安全问题

    • 由于 Object 的范围太广,可能会导致函数或类在处理参数时出现意外的行为。

5. 总结

  • 推荐使用 extends object

    • 它更严格,能够确保传入的值是一个真正的对象,而不是原始类型。
    • 它更符合 TypeScript 的类型安全设计理念。
  • 避免使用 extends Object

    • 它的范围太广,容易引入类型安全问题。
    • 它可能会接受原始类型,导致意外的隐式装箱行为。

示例对比

typescript 复制代码
// 使用 extends object(推荐)
function processObject<T extends object>(obj: T) {
  console.log(obj);
}
processObject({ name: "Alice" }); // 合法
processObject(42); // 报错:原始类型不能赋值给 object

// 使用 extends Object(不推荐)
function processObject2<T extends Object>(obj: T) {
  console.log(obj);
}
processObject2({ name: "Alice" }); // 合法
processObject2(42); // 合法,42 会被隐式装箱为 Number 对象

最终建议

在 TypeScript 中,约束对象类型时,优先使用 extends object ,以确保类型安全和代码的严谨性。只有在确实需要兼容原始类型及其包装对象的特殊场景下,才考虑使用 extends Object

相关推荐
ᥬ 小月亮4 小时前
TypeScript基础
前端·javascript·typescript
红尘散仙9 小时前
二、WebGPU 基础入门——基础知识
rust·typescript·gpu
残轩10 小时前
JavaScript/TypeScript异步任务并发实用指南
前端·javascript·typescript
红尘散仙10 小时前
一、WebGPU 基础入门——环境搭建
rust·typescript·gpu
厚礼蟹man11 小时前
一键打通api、TS、mock
前端·typescript·前端工程化
苏杰豪17 小时前
鸿蒙特效教程02-微信语音录制动画效果实现教程
typescript·动效
蒜香拿铁2 天前
【typescript基础篇】(第六章) 泛型
前端·javascript·typescript
情绪羊2 天前
Typescript Go 尝鲜体验指南
前端·typescript·github
末日的狂欢姐2 天前
AXUI前端框架v3版本已经发布,底层完全改写,基于原生技术标准,想走得更远!
javascript·typescript·前端框架·vue·react·axui