TypeScript 中的 object vs Object
目录
- 概述
- Object 类型
- object 类型
- 区别对比
- 最佳实践
- 常见陷阱
概述
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(); // 可以
特点
- 包含了 JavaScript 中所有类型的包装对象
- 可以调用 Object 原型上的方法
- 不推荐在实际开发中使用
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; // 错误
特点
- 只表示非原始类型
- 不能访问具体的属性
- 更严格的类型检查
区别对比
类型兼容性
// 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
总结
Object
(大写)
- 包含所有类型的包装对象
- 可以赋值任何类型(除了 null 和 undefined)
- 不推荐在实际开发中使用
object
(小写)
- 仅表示非原始类型
- 更严格的类型检查
- 适合用作泛型约束
- 最佳实践
- 优先使用具体的接口或类型
- 避免直接使用 Object 或 object
- 需要表示非原始类型时可以使用 object
Object不能存null和undefin ed