В TypeScript версии 2.2 был введён новый тип object. Он описывает любой непримитивный тип.
Следующие типы принято считать примитивными в JavaScript:
booleannumberstringsymbolnullundefined
Все остальные типы принято считать непримитивными.
Новый тип object представляет именно их:
// All primitive types type Primitive = | boolean | number | string | symbol | null | undefined; // All non-primitive types type NonPrimitive = object;
Давайте посмотрим, как object поможет нам более точно описывать типы.
Описания типов, использующие тип object
С релизом TypeScript версии 2.2 описания типов стандартной библиотеки были обновлены с использованием нового типа object. Например, методы Object.create() и Object.setPrototypeOf() теперь описывают параметр прототипа, как object | null:
interface ObjectConstructor { /** * Creates an object that has the specified prototype or that has null prototype. * @param o Object to use as a prototype. May be null. */ create(o: object | null): any; /** * Sets the prototype of a specified object o to object proto or null. Returns the object o. * @param o The object to change its prototype. * @param proto The value of the new prototype or null. */ setPrototypeOf(o: any, proto: object | null): any; // ... }
Если передать примитивный тип, в качестве прототипа в Object.setPrototypeOf() или в Object.create(), то, во время исполнения кода, будет выброшено исключение TypeError. Теперь TypeScript отлавливает такие ошибки на этапе компиляции:
const proto = {}; Object.create(proto); // OK Object.create(null); // OK Object.create(undefined); // Error Object.create(1337); // Error Object.create(true); // Error Object.create("oops"); // Error
Другим местом для применения типа object является структура данных WeakMap. Ключи которой должны быть объектами и не могут являться примитивами. Это требование нашло отражение в тайпингах:
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 vs Object vs {}
Возможно Вас смутит, что TypeScript определяет несколько типов, имеющих похожие имена, но представляющие разные концепции:
- object
- Object
- {}
Мы рассмотрели новый тип object выше. Теперь давайте обсудим, что же из себя представляют Object и {}.
Тип Object
Typescript определяет другой тип, с почти таким же названием, как и новый тип object, и это тип Object. В то время как object (с маленькой буквы) представляет все непримитивные типы, Object (с большой буквы) описывает функциональность, общую для все JavaScript объектов. Например, методы toString() и hasOwnProperty(). В файле lib.es6.d.ts тип Object определяется следующим образом:
interface Object { // ... /** Returns a string representation of an object. */ toString(): string; /** Returns a date converted to a string using the current locale. */ toLocaleString(): string; /** Returns the primitive value of the specified object. */ valueOf(): Object; /** * Determines whether an object has a property with the specified name. * @param v A property name. */ hasOwnProperty(v: string): boolean; /** * Determines whether an object exists in another object's prototype chain. * @param v Another object whose prototype chain is to be checked. */ isPrototypeOf(v: Object): boolean; /** * Determines whether a specified property is enumerable. * @param v A property name. */ propertyIsEnumerable(v: string): boolean; }
Тип {}
Есть ещё один тип, который очень похож: {}, пустой тип объекта. Он описывает объект у которого нет собственных свойств. При попытке доступа к произвольным свойствам такого объекта TypeScript выдаёт ошибку во время компиляции:
// Type {} const obj = {}; // Error: Property 'prop' does not exist on type '{}'. obj.prop = "value";
Тем не менее, вы можете использовать все свойства и методы, описанные в типе Object, которые неявно доступны через цепочку прототипов:
// Type {} const obj = {}; // "[object Object]" obj.toString();
