Примитивные типы Null, Undefined, Void, Never, Unknown¶
Настало время рассмотреть следующую порцию типов, некоторые из которых являются уникальными для TypeScript.
Важно¶
Прежде чем приступить к знакомству с такими типами, как Null
, Undefined
, Void
, Never
и Unknown
, стоит обговорить одну очень важную деталь. Дело в том, что все перечисленные типы можно указывать в качестве типа всем конструкциям, которые это позволяют. То есть типом данных null
можно аннотировать даже переменную (let identifier: null
). Данная книга будет изобиловать подобными примерами, так как эта возможность облегчает демонстрацию совместимости типов. Но при этом стоит понимать, что проделывать подобное в реальном коде противопоказано.
Null примитивный null тип¶
Примитивный тип Null
служит обозначением “ничего”.
Тип Null
указывается с помощью ключевого слова null
(не путать с единственным литеральным значением null
типа Null
, которое присваивается в качестве значения).
1 |
|
Тип Null
является подтипом всех типов, за исключением типа Undefined
, поэтому его единственное значение null
совместимо со всеми остальными типами данных.
1 2 3 4 5 6 7 8 |
|
В то время как тип null
совместим со всеми типами, помимо него самого, с ним самим совместим лишь тип undefined
и any
.
1 2 3 4 5 6 |
|
Тогда, когда тип данных указывается не явно, а в качестве значения используется значение null
, вывод типов определяет принадлежность к типу any
.
1 |
|
Создатели TypeScript во избежание ошибок, возникающих при операциях, в которых вместо ожидаемого значения возможно значение null
, рекомендуют вести разработку с активным флагом --strictNullChecks
. При активном флаге --strictNullChecks
тип null
является подтипом только одного типа any
. Это в свою очередь означает, что значение null
может быть совместимо только с типами any
и null
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
При активном флаге --strictNullChecks
, при условии, что в качестве значения выступает значение null
, вывод типов определяет принадлежность к типу null
.
1 |
|
Тип null
идентичен по своей работе с одноимённым типом из JavaScript.
Undefined примитивный неопределенный тип¶
Примитивный тип undefined
указывает на то, что значение не определено. Тип данных undefined
указывается с помощью ключевого слова undefined
(не путать со свойством глобального объекта undefined
, которое представляет единственное значение типа Undefined
).
1 |
|
Во время выполнения объявленные, но не инициализированные переменные, поля и свойства класса, а также параметры имеют значение undefined
. Также значение undefined
является результатом вызова методов или функций, которые не возвращают значения.
Тип undefined
является подтипом всех типов, что делает его совместимым со всеми остальными типами.
1 2 3 4 5 6 7 8 |
|
Может возникнуть вопрос, почему тип null
, который не имеет непосредственного отношения к типу undefined
, совместим с ним? На данный момент, этот вопрос так и остается неразгаданным.
В то время как тип данных undefined
совместим со всеми типами, помимо него самого, с ним совместимы лишь null
и any
.
1 2 3 4 5 6 |
|
Тогда, когда тип данных undefined
указывается не явно, компилятор устанавливает тип any
.
1 |
|
При активном флаге --strictNullChecks
, тип undefined
является подтипом только одного типа any
. Поэтому ему в качестве значения, помимо самого себя, можно присвоить только тип any
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
При активном флаге --strictNullChecks
, при условии, что в качестве значения выступает значение undefined
, вывод типов определяет принадлежность к типу undefined
.
1 |
|
Тип undefined
идентичен по своей работе с одноимённым типом из JavaScript.
Void отсутствие конкретного типа¶
Тип данных Void
можно назвать полной противоположностью типа any
, так как этот тип означает отсутствие конкретного типа. Основное предназначение типа Void
— явно указывать на то, что у функции или метода отсутствует возвращаемое значение.
Тип данных Void
указывается с помощью ключевого слова void
(не путать с одноимённым оператором из JavaScript) и, в отличие от таких типов, как null
и undefined
, не имеет никаких значений.
Тип void
является подтипом any
и супертипом для null
и undefined
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Однако с активным флагом --strictNullChecks
, тип данных void
, помимо самого себя, совместим лишь с any
и undefined
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Кому-то может показаться, что примеры чересчур излишни, или что примеры, в которых результат вызова функции, не имеющей возвращаемого значения, присваивается полям с различными типами, не имеет никакого отношения к реальности. Да, это так. Но целью данных примеров является научить думать как компилятор TypeScript.
Когда функции в качестве возвращаемого типа указан тип void
, может показаться, что возвращая различные значения с помощью оператора return
, компилятор выбрасывает ошибки из-за понимания, что функция помечена как ничего не возвращающая. Но это не так. Ошибка возникает по причине несовместимости типов.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Нельзя не упомянуть, что для функций и методов, которые ничего не возвращают и у которых отсутствует аннотация типа возвращаемого значения, вывод типов определяет принадлежность к типу void
.
1 2 3 |
|
В отличие от null
и undefined
, тип void
не имеет ни одного значения, которое могло бы явно продемонстрировать присвоение. Однако компилятор понимает, что имеет дело с типом void
при вызове функции или метода, которые не возвращают значение. Это становится ещё нагляднее, когда вывод типов устанавливает тип, полученный при вызове функции или метода, которые ничего не возвращают.
1 2 3 |
|
Тип void
является уникальным для TypeScript. В JavaScript подобного типа не существует.
Never примитивный тип¶
Примитивный типа данных Never
служит для указания того, что какие-либо операции никогда не будут выполнены.
Never
обозначается ключевым словом never
и так же, как и void
, не имеет явных значений.
Тип данных never
является подтипом всех типов, что делает его совместимым со всеми остальными типами.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Так как типу never
нельзя присвоить значение, отличное от самого типа never
, единственным местом, в котором его может использовать разработчик, является аннотация возвращаемого из функции или метода значения, с одной оговоркой. Тип never
можно указать только той функции, из которой программа действительно никогда не сможет выйти.
Такой сценарий может выражаться в виде функции, вызов которой приведет к однозначному исключению или тело функции будет включать бесконечный цикл.
1 2 3 4 5 6 7 |
|
Вывод типов определит принадлежность возвращаемого функцией значения к типу never
, только если он указан в аннотации возвращаемого типа явно.
1 2 3 4 5 6 7 8 9 10 11 |
|
Стоит заметить, что без явного указания типа never
вывод типов определит принадлежность возвращаемого значения к типу void
.
1 2 3 4 5 6 7 8 9 |
|
Тип never
является уникальным для TypeScript. В JavaScript подобного типа не существует.
Unknown¶
Тип Unknown
является типобезопасным аналогом типа any
и представлен в виде литерала unknown
. Все типы совместимы с типом unknown
, в то время как сам тип unknown
совместим только с самим собой и типом any
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Кроме того, над типом unknown
запрещено выполнение каких-либо операций.
1 2 3 4 5 6 7 8 9 |
|
Если тип unknown
составляет тип пересечение (intersection
), то он будет перекрыт всеми типами.
1 2 3 4 5 6 7 8 9 10 |
|
Если тип unknown
составляет тип объединение (union
), то он перекроет все типы, за исключением типа any
.
1 2 3 4 5 6 7 8 9 10 |
|
Помимо этого, запрос ключей (keyof
) для типа unknown
возвращает тип never
.
1 2 3 |
|
Тип unknown
позволяется использовать только в операциях равенства ===
, ==
, !==
и !=
и в операциях с логическими операторами &&
, ||
и !
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Также стоит упомянуть, что функция, у которой возвращаемый тип принадлежит к типу unknown
, может не возвращать значение явно.
1 2 3 4 5 6 7 8 9 |
|
При активной опции --strictPropertyInitialization
принадлежащие к типу unknown
поля не нуждаются в инициализации.
1 2 3 4 5 |
|
Если в определении типа данных участвует сопоставленный тип (Mapped Type
), которому в качестве аргумента типа передается тип unknown
, то такой сопоставленный тип будет выведен как объектный тип {}
. Поскольку сопоставленные типы (Mapped Types
), псевдонимы типов (types
), а также обобщения (Generics<>
) будут рассмотрены позднее, то стоит просто помнить об этом факте и повторно прочесть написанное при необходимости.
1 2 3 4 5 6 7 |
|