特殊对象类型

TypeScript 中,定义了几种特殊的对象类型——objectObject{},它们有相似的名字或概念,但又各有区别,接下来将分别介绍。注意,在实际使用时,只建议使用objectObject{} 不建议使用。

object

object(首字母小写)类型是 TypeScript 新增的类型,用于表示非原始类型。在 TypeScript 中,原始类型有 numberstringbooleanbigintsymbol。因此,object 类型表示除此以外的全部类型。

以下赋值代码会引起编译错误。

let a: object;
//编译错误:不能将类型"number"分配给类型"object"。ts(2322)
a = 1;
//编译错误:不能将类型"bigint"分配给类型"object"。ts(2322)
a = 1n;
//编译错误:不能将类型"boolean"分配给类型"object"。ts(2322)
a = true;
//编译错误:不能将类型"string"分配给类型"object"。ts(2322)
a = "";
//编译错误:不能将类型"symbol"分配给类型"object"。ts(2322)
a = Symbol();

以下为正确的赋值代码。

let a: object;
a = { name: "hello" };
a = [0, 1, 2, 3];
a = function () { console.log("hello") };
a = new Date(); //时间对象,它是一种内置对象,后面将详细介绍

注意,当对象为 object 类型时,因为 object 类型是一种泛指的类型,并不是具体的类型,因此无法得知它支持哪些属性或方法,需要将其转换为具体的类型才能操作。

let a: object = [1, 2, 3, 4];
let b: object = { name: "rex" };
let c: object = function () { console.log("hello world!") }

//以下使用方式将引起编译错误
//编译错误:类型"object"上不存在属性"length"。ts(2339)
console.log(a.length);
//编译错误:类型"object"上不存在属性"name"。ts(2339)
console.log(b.name);
//编译错误:此表达式不可调用。类型 "{}" 没有调用签名。ts(2349)
c();

//以下是正确的使用方式
console.log((a as number[]).length);
console.log((b as { name: string }).name);
(c as () => void)();

object 类型可用于参数传递过程中的处理。假设某函数要求能传入任意的非原始类型,则可以将其定义为 object 类型,而非 any 类型,示例代码如下。

function handleObject(obj: object) {
    //...
}

Object和{}

Object{} 类型都是 TypeScript 中不推荐使用的类型,这里只做简单介绍。这两种类型主要用于 JavaScriptTypeScript 中只保留了它们的功能。

Object 类型的字面意义是对象类型,{} 类型的字面意义是没有属性或方法的初始空对象类型,但它们不仅可以初始化为非原始类型,还可以初始化为原始类型。这是一个让人迷惑的设计,同时通常会引起误操作(这也是 TypeScript 中又引入 object 类型来表示非原始类型的原因)。示例代码如下。

let a: Object; //或者let a: {};
a = 1;
a = 1n;
a = true;
a = "";
a = Symbol();
a = { name: "hello" };
a = [0, 1, 2, 3];
a = function () { console.log("hello") };
a = new Date();

{} 类型相比,Object 类型还支持各种方法(如 Object.create()Object.setPrototypeOf() 方法等),这些方法通常用于原型和继承的处理,但在 TypeScript 中已经有比较完善的接口及类,它们可以处理继承关系,因此无须再使用这些落后的方式。感兴趣的读者可以自行研究。