https://habr.com/ru/company/ruvds/blog/468229/- Блог компании RUVDS.com
- Разработка веб-сайтов
- JavaScript
- TypeScript
Если вы, до того, как заинтересовались JavaScript, писали на традиционных языках с сильной типизацией, то вы, возможно, знакомы с концепцией
void
. Это — тип, использование которого сообщает программисту о том, что соответствующие функции и методы при их вызове ничего не возвращают.
Сущность
void
имеется также в JavaScript и TypeScript. В JS это — оператор. В TS это примитивный тип данных. И там и там
void
ведёт себя не так, как могли бы ожидать многие из тех, кто сталкивался с
void
в других языках.
Оператор void в JavaScript
В JavaScript оператор
void
вычисляет переданное ему выражение. При этом, независимо от того, какое именно выражение вычисляется,
void
всегда возвращает
undefined
.
let i = void 2; // i === undefined
Зачем вообще нужен подобный оператор?
Во-первых, надо отметить, что в ранние годы JS-программирования разработчики могли переопределять
undefined
и записывать в него какое-нибудь своё значение. А вот
void
всегда возвращает настоящее значение
undefined
.
Во-вторых — использование оператора
void
— это интересный способ работы с немедленно вызываемыми функциями:
void function() {
console.log('What')
}()
И всё это — без загрязнения глобального пространства имён:
void function aRecursion(i) {
if(i > 0) {
console.log(i--)
aRecursion(i)
}
}(3)
console.log(typeof aRecursion) // undefined
Так как оператор
void
всегда возвращает
undefined
и всегда вычисляет переданное ему выражение, в нашем распоряжении оказывается весьма выразительный способ возвращения из функции без возврата какого-то значения, но с вызовом, например, некоего коллбэка:
// возврат чего-то кроме undefined приведёт к аварийной остановке приложения
function middleware(nextCallback) {
if(conditionApplies()) {
return void nextCallback();
}
}
Это приводит нас к самому важному способу использования
void
. Данный оператор представляет собой нечто вроде «поста охраны» приложения. Если некая функция всегда должна возвращать
undefined
— обеспечить это можно, воспользовавшись оператором
void
.
button.onclick = () => void doSomething();
Тип данных void в TypeScript
Тип
void в TypeScript можно назвать чем-то вроде противоположности типа
any
. Функции в JavaScript всегда что-то возвращают. Это может быть либо некое заданное программистом значение, либо
undefined
:
function iHaveNoReturnValue(i) {
console.log(i)
} // возвращает undefined
Так как JavaScript функции, из которых явным образом ничего не возвращается, всегда возвращают
undefined
,
void
в TypeScript является подходящим типом, сообщающим разработчикам о том, что функция возвращает
undefined
:
declare function iHaveNoReturnValue(i: number): void
Сущность
void
в виде типа можно ещё использовать для параметров и для любых других объявлений переменных. Единственное значение, которое всегда можно передать void-параметру — это
undefined
.
declare function iTakeNoParameters(x: void): void
iTakeNoParameters() // ОК
iTakeNoParameters(undefined) // ОК
iTakeNoParameters(void 2) // ОК
В результате оказывается, что в TS типы
void
и
undefined
— это почти одно и то же. Но между ними есть одно маленькое различие, которое, на самом деле, чрезвычайно важно. Возвращаемый тип
void
может быть заменён на другие типы, что позволяет реализовывать продвинутые паттерны работы с коллбэками.
function doSomething(callback: () => void) {
let c = callback() //здесь callback всегда возвращает undefined
//тип c - тоже undefined
}
// эта функция возвращает число
function aNumberCallback(): number {
return 2;
}
// работает; обеспечивается типобезопасность в doSometing
doSomething(aNumberCallback)
Разработчики ожидают от подобных конструкций, часто используемых в JS-приложениях, именно такого поведения.
Вот материал на эту тему.
Если вы хотите, чтобы функция принимала бы лишь функции, которые возвращают
undefined
— вы можете соответствующим образом изменить сигнатуру метода:
// было
// function doSomething(callback: () => void) {
// стало
function doSomething(callback: () => undefined) { /* ... */ }
function aNumberCallback(): number { return 2; }
// Ошибка - типы не совпадают
doSomething(aNumberCallback)
Итоги
Оператор
void
в JavaScript и тип данных
void
в TypeScript — сущности довольно простые и понятные. Круг ситуаций, в которых они применимы, ограничен. Однако надо отметить, что программист, который их использует, скорее всего, не столкнётся при работе с ними с какими-то проблемами.
Уважаемые читатели! Пользуетесь ли вы
void
в JS и TS?