Я вызываю размер функция из TypeScript. Поскольку я имею дело с числами, его возвращаемый тип - [number, number] | [undefined, undefined].

Какой идиоматический способ предоставить значение по умолчанию в случае [undefined,undefined]?

В итоге я написал вспомогательную функцию:

import { extent } from 'd3-array';

...

/**
 * Provides a safe [0, 0] default for potentially undefined value pairs.
 */
export const safe = ([x, y]: [number, number] | [undefined, undefined]): [number, number] => {
    if (x === undefined || y === undefined) {
        return [0, 0];
    } else {
        return [x, y] as [number, number];
    }
};

const safeExtent = safe(extent(values));

Но я ищу более элегантный / идиоматический способ, что-то вроде Option(extent).getOrElse([0, 0]).

1
Rahel Lüthy 13 Мар 2018 в 14:59

2 ответа

Лучший ответ

Я не знаю встроенной функции TypeScript / JavaScript, которая обрабатывает какое-то определенное состояние на основе значений массива. Вызов функции уменьшения не требуется для массива, содержащего ровно два значения.

Я бы сделал это так:

export function safe([x, y]: [number|undefined, number|undefined]): [number, number] {
    return (x === undefined || y === undefined) ? [0, 0] : [x, y];
}

Тесты:

// = [0, 0]
safe([undefined, 1])

// = [0, 0]
safe([1, undefined])

// = [0, 0]
safe([undefined, undefined])

// = [1, 1]
safe([1, 1])

// = [null, null]
safe([null, null])

Примечания: я предпочитаю экспортировать объявления функций, а не литералы типов функций (понятие лямбда), но я думаю, что это дело вкуса.

Однако имеет значение использование функций и константных лямбда-выражений внутри класса, поскольку this определен как экземпляр класса в константном лямбда-члене.

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

Обновление: вы также можете использовать объявление типа:

export type numberOpt = number | undefined;

export function safe([x, y]: [numberOpt, numberOpt]): [number, number] {
    return (x === undefined || y === undefined) ? [0, 0] : [x, y];
}

Однако это означает еще один экспорт.

Обновление 2: даже лучше, потому что более общий и, следовательно, ближе к вашему вопросу:

export type Option<T> = T | undefined;

export function safe([x, y]: [Option<number>, Option<number>]): [number, number] {
    return (x === undefined || y === undefined) ? [0, 0] : [x, y];
}
1
Daniel Dietrich 14 Мар 2018 в 13:24

Это сработает?

type optionalNumber = number | undefined

export const safe = ([x, y]: [optionalNumber, optionalNumber]): [
    number,
    number
] => {
    return [x, y].map(num => num || 0)
}

Обновление 1

После того, как я неправильно понял вопрос и ваше объяснение в комментарии, я смог придумать только следующее:

export const safe = ([x, y]: [number, number] | [undefined, undefined]): [
    number,
    number
] => {
    return [x, y].map(num => num || 0) as [number, number]
}

Я вижу .map () убирает кортеж кортежа

Учитывая однородный характер ввода, он работает, и я думаю, что он выглядит чище, но я не знаю, самый ли это идиоматический способ.

0
Pravin 14 Мар 2018 в 09:09