Примитивные типы 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 | |