TypeScript之Object、object、{ }的區(qū)別

對于JavaScript而言,只有(大)Object,沒有(小)object
object 只是 typeof 返回的一個字符串

typeof null === "object"  // true
typeof {} === "object"  // true

對于TypeScript來說,同時存在 objectObject

object

object 是TypeScript v2.2 引入的新類型,用于正式表示對象類型。
至此,TypeScript的原始類型(number、string、bigint、boolean、symbol、null、undefined、object)對應的正是JavaScript定義的 8 種內置類型:Number、String、BigInt、Boolean、Symbol、Null、Undefined、Object
當然,TypeScript還定義了其他重要的類型:unknown、never、void、數(shù)組、元組、函數(shù)
object 表示任何非原始值類型,包括對象、函數(shù)、數(shù)組等
當對object類型的變量賦予原始值時,TS編譯器會報錯

let a: object;
a = {};
a = [1, 2, 3];
a = [1, true, "abc"];
a = () => 1;

a = 11;  // error 不能將類型"number"分配給類型"object"

JavaScript WeakMap 要求鍵必須是對象,TypeScript 在定義 WeakMap 時 使用的正是 object 約束鍵的類型

interface WeakMap<K extends object, V> {
    delete(key: K): boolean;
    get(key: K): V | undefined;
    has(key: K): boolean;
    set(key: K, value: V): this;
}

Object

TS把 JavaScript Object 分成了兩個接口來定義:

  1. Object 接口(類型) 用于定義 JS Object 的原型對象Object.prototype
interface Object {
    constructor: Function;
    toString(): string;
    toLocaleString(): string;
    valueOf(): Object;
    hasOwnProperty(v: PropertyKey): boolean;
    isPrototypeOf(v: Object): boolean;
    propertyIsEnumerable(v: PropertyKey): boolean;
}
  1. ObjectConstructor 用于定義 Object 自身的屬性,如Object.create()
interface ObjectConstructor {
    new(value?: any): Object;
    (): any;
    (value: any): any;
    readonly prototype: Object;
    getPrototypeOf(o: any): any;
    getOwnPropertyNames(o: any): string[];
    create(o: object | null): any;
    defineProperty<T>(o: T, p: PropertyKey, ...): T;
    freeze<T>(a: T[]): readonly T[];
    freeze<T extends Function>(f: T): T;
    freeze<T>(o: T): Readonly<T>;
    // ...
}

Object 的所有實例都繼承了 Object 接口的所有屬性/方法:

function f(x: Object): { toString(): string } {
    return x; // OK
}

object 類型也可以訪問Object接口上定義的所有屬性/方法

let bar: object = {};
bar.toString(); // "[object Object]"
bar.hasOwnProperty("abc");  // false

有趣的是,由于JavaScript的裝箱拆箱機制,基本類型有能力訪問Object.prototype原型對象上的屬性。
因此,在 TS Object 類型可以同時接受引用類型和基本類型(不包括undefinednull)。但 object 類型不能接受原始值。

let b: Object = 3;  // OK
let h: object = 4;  // error

因此,在約束類型為非原始值類型時,應當始終使用 object!

需要注意的是,如果Object類型的值對象屬性名與Object接口定義的屬性沖突,則TS編譯報錯。

let b: Object = { 
   toString() { return 123 } // Error
};

object 類型不會。

{ }

{ } 描述一個沒有成員的對象,試圖訪問它的任何屬性時,TS都會編譯錯誤。
但仍然可以訪問 Object 類型上的所有屬性/方法

const obj: {} = {};

obj.toString(); // "[object Object]"

{} 也可以被賦予原始值

let foo: {};
foo = 3;    // OK

雖然 Object{} 都可以接受基本類型的值,但并不包括 nullundefined。

// 不能將類型 null 分配給類型 {}
let foo: {} = null;  // error
// 不能將類型 undefined 分配給類型 Object
let bar: Object = undefined;  // error

可以明顯感覺到,{ }Object 的效果幾乎一樣,即 {} == Object,但 Object 更規(guī)范。

object 是一個寬泛的通用的非基本類型

let foo: { [key: string]: string } = {};
let bar: object = {};
bar = foo; // OK
// 不能將類型 object 分配給類型 { [key: string]: string; }
foo = bar; // Error

總結

object 是TypeScript v2.2引入的一種非基本類型,不能被賦予原始值。
Object 是對TypeScript對JavaScript Object.prototype原型對象的定義,是所屬對象類型的頂層類型,即所有對象類型都繼承了Object中定義的屬性/方法。同時,由于JavaScript的拆箱裝箱機制,Object類型的變量可以被賦予原始值,而基本類型也可以訪問Object中定義的屬性/方法。
{} 是一個沒有任何成員的對象類型,它可以訪問Object中定義的屬性/方法,也可以被賦予原始值。

因此,在約束對象類型時,我們應該始終使用object!

其實,不止有 Objectobject,還有 Numbernumber、Booleanboolean、Stringstring 等等。
Object、Number、Boolean 都定義在TypeScript內置的 .d.ts 中,對我們是可見的;而 object、number、boolean 這些TS的內置原始類型 都是不可見的。
在開發(fā)中,我們應當始終使用這些原始類型,而不是使用Object、Number、Boolean

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容