Можно ли преобразовать undefined в void в TS?

TL; DR;

Это нормально? Или это плохая практика?

function isUndefined (payload: any): payload is undefined | void {
  return payload === undefined
}

Контекст

В TypeScript у меня есть функция, которая может возвращать что-то или undefined или void.

Что-то вроде обработчика событий, который может возвращать измененную полезную нагрузку, или разработчик может ничего не возвращать или не определять, если они не будут изменять полезную нагрузку:

function eventHandler <T extends {[key: string]: any}> (payload: T): Modified<T> | undefined | void {
  // ... implementation
}

Затем у меня есть средство проверки типов, которое должно проверить, возвращает ли оно что-то, кроме void или undefined:

const result = eventHandler(payload)

if (result !== undefined) {
  // we have a modified payload!
}

Однако в приведенном выше фрагменте я получаю сообщение об ошибке, потому что в нем говорится, что даже если result !== undefined это все еще может быть void?

На мой взгляд, это странно, потому что void должно быть таким же, как undefined.

Итак, я сделал эту проверку типов, которая ее решает:

function isUndefined (payload: any): payload is undefined | void {
  return payload === undefined
}

Это решает мою проблему, но мой вопрос:

Это нормально? Или это плохая практика?

2 ответа

Решение

void не является undefined. void означает отсутствие возвращаемого значения. undefined - это тип значения, неопределенного во время выполнения.

это правда, что функция, которая не возвращает значения во время выполнения, возвращает undefined, но в системе типов TS мы решили сделать отсутствие возвращаемого значения особенным.

Например, присвоение (a) => void to (a) => number | undefined скорее всего, это ошибка, хотя во время выполнения это безопасно.

В общем, не используйте void, за исключением возвращаемого типа функций. для всего остального используйтеundefined.

Итак, да, нам нужно будет использовать другую проверку для undefined а также void.

Я думаю, вы усложняете это дело, чем должно быть. Функция, возвращающаяvoid Можно:

  1. Нет заявления о возврате
  2. Есть return; инструкция без указания значения.
  3. Есть return undefined; заявление.

В чистом javascript все вышеперечисленное будет иметь возвращаемое значение undefined. Если вы говорите, что функция возвращаетundefined, то вы можете делать только №2 и №3 из приведенного выше списка.

Таким образом, вы можете просто иметь тип функции, который объединяет voidс чем угодно.

function foo(): string | void {
    return Math.random() > 0.5 ? 'abc' : 123
}

const val = foo()
if (val === undefined) {
    console.log('is undefined', val)
} else {
    console.log('is some value', val)
}

Это означает, что вы можете создать универсальный тип функции, который изменяет полезные данные следующим образом:

type PayloadModifier<T extends {[key: string]: any}> = (payload: T) => T | void

const setMaxAsTen: PayloadModifier<{a: number}> = (payload) => {
    if (payload.a > 10) {
        return { a: 10 }
    }
    return undefined // required unless noImplicitReturns is false
}

const val = setMaxAsTen({a: 5})
if (val === undefined) {
    console.log('is undefined', val)
} else {
    console.log('is some value', val)
}

Детская площадка

Последнее, что следует отметить, это то, что есть параметр компилятора, который хорошо оставить на вызываемомnoImplicitReturns. если функция объявляет возвращаемое значение в любой ветви выполнения, то возвращаемое значение должно быть объявлено в каждой ветви выполнения. Поэтому, поскольку приведенное выше иногда возвращает значение, вы должны явно вернутьundefinedесли вы не вернете полезную нагрузку. Вы можете отключить эту опцию, позволяя вам опустить эту строку, но это не рекомендуется, так как это помогает вам отловить некоторые ошибки.

Другие вопросы по тегам