Заметка о void в 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?


Источник: https://habr.com/ru/company/ruvds/blog/468229/


Интересные статьи

Интересные статьи

Шел очередной день самоизоляции, и я делал один из тех проектов для себя, которые мы забрасываем через пару дней после того как начали. Ну вы знаете, тот проект, который сделает вас з...
Эта статья для тех, кто собирается открыть интернет-магазин, но еще рассматривает варианты и думает по какому пути пойти, заказать разработку магазина в студии, у фрилансера или выбрать облачный серви...
TL;DR VKScript — это не JavaScript. Семантика этого языка кардинально отличается от семантики JavaScript. См. заключение. Читать дальше →
Друзья, в преддверии выходных хотим поделиться с вами еще одной интересной публикацией, которую хотим приурочить к запуску новой группы по курсу «Разработчик JavaScript». Потратив последни...
Тема статьи навеяна результатами наблюдений за методикой создания шаблонов различными разработчиками, чьи проекты попадали мне на поддержку. Порой разобраться в, казалось бы, такой простой сущности ка...