В TypeScript
версии 2.2 был введён новый тип object
. Он описывает любой непримитивный тип.
Следующие типы принято считать примитивными в JavaScript
:
boolean
number
string
symbol
null
undefined
Все остальные типы принято считать непримитивными.
Новый тип 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();
Комментарии (18)
DarkByte2015
16.01.2018 17:21Вообще это нормально, но они зря его назвали также как существующий Object. Будет большая путаница несмотря на все объяснения. Разница в регистре одной буквы это не о чем. Вообще это очень напоминает C#. Там есть классы (class) и структуры (struct). Под структурой понимается любой ValueType (числа, булевые значения, в общем примитивные типы), а под классами как раз — классы (то что тут назвали object). Также есть корень иерархии — тип System.Object (можно с маленькой буквы object — алиас просто). Короче я о том что надо было поднапрячься и все же придумать имя получше…
tenbits
17.01.2018 03:07На самом деле, такое наименование следует тому же принципи что и
Number
:number
,String
:string
,Boolean
:boolean
. С этим же ни у кого проблем не возникает.DarkByte2015
17.01.2018 09:19Тогда это скорее как в Java. Там тоже есть примитивный int, а есть объект Integer.
mayorovp
17.01.2018 09:57Именно так и есть. Точно так как и в Java,
Number
— это упакованная версияnumber
.
Разве что вот теперь
Object
иobject
отличаются не упакованностью, а занимают разные места в иерархии наследования...
FlamyXD
16.01.2018 17:22Разве null и undefined являются типами? А не значениями?
SayLovePlz Автор
16.01.2018 17:22FlamyXD
16.01.2018 17:34Там написано, что это «Специальное значение».
DarkByte2015
16.01.2018 17:52+1Значение null не относится ни к одному из типов выше, а образует свой отдельный тип, состоящий из единственного значения null
FlamyXD
16.01.2018 19:58-1Это просто специальное значение, которое имеет смысл «ничего» или «значение неизвестно».
Vadem
17.01.2018 17:12+1Строго говоря, стандарт определяет именно отдельные типы для null и undefined:
ECMAScript Language Types
И у них ровно по одному значению.
vanxant
Мммм, я правильно понимаю, что построили сначала строго-типизированную надстройку над мерзко-утино-почтине-типизированным javascript, а потом, через N лет, это всё решили отменить?)
Shtucer
Нет. Это было сделано раньше. Тип
any
был с самого сразу. Иначе, как бы оно дружило с JS?vanxant
Нет, ну
any
этоany
. Заглушка в стиле «возвращает то, не знаю что». Аobject
это именно объект, просто с утиной типизацией (т.е. требования к наличию определённых свойств в этом объекте определяются нижележащим кодом).Shtucer
Ну, как бы
any
, как мне кажется, делает "строго-типизированную надстройку" не такой уж и строгой прям с фундамента. Заглушкаany
не только про "возвращает то, не знаю что". Ее можно пихать во все места и не заморачивать мозг всеми этими типизациями. Сobject
уже не то манто. Как, повторюсь, мне кажется.eliduvid
На сколько я понял из статьи это тоже заглушка типа any, которая только проверяет на не примитвность. Это не значит, что можно обращаться к любым свойствам без приведения.
PYXRU
Благодаря этой заглушки они усилили типизацию как раз, потому что теперь если метод принципе не может принять примитив он не будет допущен ts компилятором. any — такое бы позволил.
alex6636
Что не отменяется мерзости js
mayorovp
Нет, они ввели новый тип для того чтобы более точно описать некоторые существующие интерфейсы. Например, тот же
Object.create
. Каким образом уточнение модели ее вдруг отменяет?