TypeScript 中的 object vs Object

目录

  1. 概述
  2. Object 类型
  3. object 类型
  4. 区别对比
  5. 最佳实践
  6. 常见陷阱

概述

TypeScript 中有两种表示对象的类型:Object(大写)和 object(小写)。它们有着不同的语义和使用场景。

Object 类型

定义

Object 类型是所有 Object 类的实例的类型,它包含了所有内置对象的原型方法:

  • toString()
  • hasOwnProperty()
  • valueOf()
    等等

示例

// Object 类型可以包含任何值
let obj1: Object = { x: 10 };
let obj2: Object = "Hello";  // 可以,字符串对象
let obj3: Object = 42;       // 可以,数字对象
let obj4: Object = true;     // 可以,布尔对象
let obj5: Object = null;     // 错误
let obj6: Object = undefined;// 错误

// 可以访问 Object 原型上的方法
obj1.toString();       // 可以
obj1.hasOwnProperty(); // 可以

特点

  1. 包含了 JavaScript 中所有类型的包装对象
  2. 可以调用 Object 原型上的方法
  3. 不推荐在实际开发中使用

object 类型

定义

object 类型表示非原始类型,即任何不是 number、string、boolean、bigint、symbol、null 或 undefined 的类型。

示例

// object 类型只能是对象
let obj1: object = { x: 10 };     // 可以
let obj2: object = [1, 2, 3];     // 可以,数组也是对象
let obj3: object = new Set();     // 可以
let obj4: object = new Map();     // 可以

// 原始类型值不能赋给 object
let obj5: object = 42;            // 错误
let obj6: object = "Hello";       // 错误
let obj7: object = true;          // 错误
let obj8: object = null;          // 错误
let obj9: object = undefined;     // 错误

特点

  1. 只表示非原始类型
  2. 不能访问具体的属性
  3. 更严格的类型检查

区别对比

类型兼容性

// Object 可以接收几乎所有类型(除了 null 和 undefined)
let objectType: Object = 42;        // OK
let objectType2: Object = "string"; // OK
let objectType3: Object = true;     // OK
let objectType4: Object = {};       // OK

// object 只接收非原始类型
let objectLiteral: object = 42;        // Error
let objectLiteral2: object = "string"; // Error
let objectLiteral3: object = true;     // Error
let objectLiteral4: object = {};       // OK

属性访问

// Object 类型
let obj1: Object = { x: 10 };
obj1.toString();           // OK
obj1.hasOwnProperty("x"); // OK
obj1.x;                   // Error: Property 'x' does not exist on type 'Object'

// object 类型
let obj2: object = { x: 10 };
obj2.toString();           // OK
obj2.hasOwnProperty("x"); // OK
obj2.x;                   // Error: Property 'x' does not exist on type 'object'

实际应用

// 推荐:使用具体的接口或类型
interface Point {
  x: number;
  y: number;
}

let point: Point = { x: 10, y: 20 };  // 最佳实践

// 不推荐:使用 Object
let badPoint: Object = { x: 10, y: 20 };  // 失去类型检查

// 不推荐:使用 object
let alsobadPoint: object = { x: 10, y: 20 };  // 无法访问属性

最佳实践

1. 使用具体的类型

// 好的做法
interface User {
  name: string;
  age: number;
}

function processUser(user: User) {
  console.log(user.name);  // 可以访问具体属性
}

// 避免的做法
function processObject(obj: Object) {
  console.log(obj.name);  // Error: Property 'name' does not exist on type 'Object'
}

2. 泛型约束

// 使用 object 作为泛型约束
function clone<T extends object>(obj: T): T {
  return { ...obj };
}

// 正确使用
clone({ x: 10 });    // OK
clone([1, 2, 3]);    // OK
clone(42);           // Error: Argument of type 'number' is not assignable to parameter of type 'object'

3. 类型保护

function isObject(value: unknown): value is object {
  return typeof value === "object" && value !== null;
}

function processValue(value: unknown) {
  if (isObject(value)) {
    // value 的类型在这里是 object
    Object.keys(value);  // OK
  }
}

常见陷阱

1. null 的处理

// 注意:typeof null === "object"
let value: unknown = null;
console.log(typeof value === "object");  // true

// 正确的检查方式
function isNonNullObject(value: unknown): value is object {
  return typeof value === "object" && value !== null;
}

2. 数组类型

// 数组是 object 类型
let arr: object = [1, 2, 3];  // OK
let arr2: Object = [1, 2, 3]; // OK

// 但无法访问数组方法
arr.length;   // Error
arr.push(4);  // Error

// 应该使用具体的数组类型
let arr3: number[] = [1, 2, 3];
arr3.length;  // OK
arr3.push(4); // OK

总结

  1. Object(大写)
  • 包含所有类型的包装对象
  • 可以赋值任何类型(除了 null 和 undefined)
  • 不推荐在实际开发中使用
  1. object(小写)
  • 仅表示非原始类型
  • 更严格的类型检查
  • 适合用作泛型约束
  1. 最佳实践
  • 优先使用具体的接口或类型
  • 避免直接使用 Object 或 object
  • 需要表示非原始类型时可以使用 object

    Object不能存null和undefin ed