Проверка типа аргумента Javascript - PullRequest
0 голосов
/ 07 июня 2019

Я исчерпал свое Google-фу, пытаясь найти примеры того, как наилучшим образом утверждать параметры в методах модуля ES6 или иметь дело с неопределенностью типа данных, которые могут быть переданы.А именно между такими вещами, как строки и числовые типы.Я только несколько часов ломал голову над странным поведением вокруг вычисляемого свойства и MobX, где у меня есть некоторый тестовый код, который инициализирует отправленную по умолчанию отправленную величину, и это прекрасно работает.Вычисленное значение принимает начальное значение, суммирует две суммы из связанных данных (кредиты и дебеты), затем добавляет дебеты и вычитает кредиты, чтобы вернуть скорректированное значение.Таким образом, возвращаемое initialValue (1000) + totalDebits (0) - totalCredits (0), которое возвращает 1000. Простой.Однако, когда я добавил диалог для ввода нового элемента в список с начальным значением 2000, мое вычисленное значение возвращалось как 20000!Что было более странным, так это то, что я сохраняю эти объекты в локальном хранилище, и когда я обновляю сохраненные значения, вычисленная сумма все еще имела 20000, но другие существующие значения имели правильные вычисленные значения, соответствующие их начальным значениям.

Я наконецдействительно отследил причину этого и подтвердил в постоянном состоянии, что мой initialBalance с введенной страницы хранился как «2000», строковый литерал.«2000» + 0 - 0, который добавил 0 к строке, в то время как минус был проигнорирован.

Мой вопрос: какие есть варианты с простым JS или подходящей библиотекой ES6 для обработки типов, которые могут попадать вфункция, такая как действие MobX?Плюс любой совет для лучших практик при работе с аргументами JS в целом.

Например: в моем компоненте у меня есть событие onChange

onInitialBalanceChange(e){
    const value = e.target.value;
    const account = this.state.account;
    let validationError = null;
    let isBalanceValid = true;
    if(!this.validateInitialBalance(value)){
        validationError = 'The initial balance must be a positive number.'
        isBalanceValid = false;
    } 
    account.updateInitialBalance(value);
    this.setState({validationError: validationError, isBalanceValid: isBalanceValid, isComplete: isBalanceValid && this.state.isNameValid});
}

updateInitialBalance зарегистрирован как действие MobX:

updateInitialBalance(initialBalance){
    if (!!initialBalance) this.initialBalance = initialBalance;
    return this;
}

Вот где мой вопрос / беспокойство, и мое удивление в том, что я действительно мало что видел в рассмотрении типов аргументов JS и преобразовании типов, помимо объяснений функций, которые выполняют отдельные проверки.Мой компонент выполняет проверочную проверку баланса и может вернуть баланс в виде числа, но при этом метод обновления все еще может вызываться в другом месте с числовой строкой.У меня есть утверждение, что аргумент не является пустым / пустым, но каковы наилучшие практики для утверждения / преобразования его типа, кроме значительного числа условий if ()?initialBalance может быть строкой «2000» или числом 2000, и он также должен защищать от недопустимых данных, таких как «fred» ??Поэтому я поставил вопрос о надежной проверке типов в мире с утками.

Судя по тому, что я вижу, это работает, но на основании документации это выглядит немного "неправильно":

if (!!initialBalance) this.initialBalance = parseInt(initialBalance);

parseInt принимает "строку", однако, если initialBalance уже является числом (не числовой строкой), это также работает.

Я знаю, что это немного надуманный вопрос, но я действительно ищу варианты, потому что крик в моих ушах от разработчика C # во мне становится оглушительным.:)

1 Ответ

1 голос
/ 07 июня 2019

Похоже, здесь есть три вопроса.Это всего лишь некоторые мнения, которые, я думаю, должны помочь с каждым.

Как мне лучше всего получить доступ к локальному хранилищу?

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

class LocalStorageWrapper {

    setInitialBalanace(balance){
        if(Object.prototype.toString.call(balance) !== '[object Number]') return false;
        // any other validation. > 0? < 9999999? etc
        // set the value
    }

    getInitialBalance(){
        const val = // get the value from local storage
        if(!isNaN(parseFloat(val)) && isFinite(val)) return parseInt(val);
        if(Object.prototype.toString.call(val) === '[object Number]') return val;
        // return some default value. The value is either unset or corrupted
    }
}

Примечания:

  • Используйте это, чтобы получить доступ к localalstorage по всей базе кода, чтобы избежать повторных проверок везде.Также модульное тестирование дерьма из него.
  • Object.prototype.toString.call(balance) !== '[object Number]' - это IMO лучший способ проверить значимое число.См. здесь для тестовых случаев.
  • !isNaN(parseFloat(val)) && isFinite(val) - это лучший способ для проверки «числового» значения, которое можно надежно проанализировать для числа.

Есть ли удобный шаблон для проверки ошибок пользователя

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

onInitialBalanceChange(e){

    try {
        if(!this.validateInitialBalance(value)){
            throw new Error('initial_balance_negative')
        }
        // other error checks here...
        account.updateInitialBalance(value); // do whatever you want
        this.setState({validationError: null, isBalanceValid: isBalanceValid, isComplete: isBalanceValid && this.state.isNameValid});
    } catch(e) {
        // ideally match against some expected
        if(constantStrings.hasOwnProperty(e.message)){
            this.setState({validationError: constantStrings[e.message]}); // an 'expected' user error
        }else{
            this.setState({validationError: 'Unknown error'}); // a 'true' error
        }
    }

}

// somewhere else in 'strings.js' or something
const constantStrings = {
    initial_balance_negative: 'The initial balance must be a positive number.'
};

JS с утиным шрифтом сложный

Я знаю :(. Но я настоятельно рекомендую Typescript. Кривая обучения действительно не слишком крутаяи если это вариант для вашего проекта, используйте его. Он заблаговременно обнаружит множество ошибок для вас (включая ошибку local-storage-is-a-string-value-store) и избавит вас от всех проблем, тестирующих эти модули.вещи.

...