I've been exhausting my Google-fu trying to find examples on how to best assert parameters in ES6 module methods, or deal with the uncertainty of the type of data that may get passed around. Namely between things like strings and numeric types. I've just been scratching my head for a few hours with a weird behaviour issue around a computed property and MobX where I have some test code that initializes a default sent of values and that works just fine. The computed value takes an initial value, sums up two totals from related data (credits and debits) then adds the debits and deducts the credits to return the adjusted value. So the return initialValue (1000) + totalDebits (0) - totalCredits (0) which returns 1000. Simple. However when I added a dialog to enter a new item to the list with an initial value of 2000, my computed value was coming back as 20000! What was stranger is that I persist these objects to local storage and when I refresh from the stored values the computed total still had 20000, but the other existing values had the correct computed values matching their initial values.
I finally did track down the reason for it, and verified it in the persisted state that my initialBalance from the entered page was being stored as "2000", a string literal. "2000" + 0 - 0 which added a 0 to the string, while the minus was ignored.
My question is what options are there with plain JS or suitable ES6 library for handling types that might be coming into a function such as a MobX action? Plus any advice for best practices when dealing with JS arguments in general.
For example: In my component I have an onChange event
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});
}
the updateInitialBalance is registered as a MobX action:
updateInitialBalance(initialBalance){
if (!!initialBalance) this.initialBalance = initialBalance;
return this;
}
This is where my question/concern is, and my surprise that I haven't really seen much out there on addressing JS argument types and type conversion beyond explanations of functions that do individual checks. My component does a validate check on the balance, and could return a balance as number, but that still leaves the update method potentially still being called elsewhere with a numeric string. I have an assertion that the argument isn't null/empty, but what are the best practices for asserting/converting it's type other than a significant # of if() conditions? initialBalance may be a string "2000" or a number 2000 and it should also guard against invalid data such as "fred"?? So I put the question out there for reliable type checking in a duck-typed world.
From what I can see this appears to work, but it just feels a bit "wrong" based on the documentation:
if (!!initialBalance) this.initialBalance = parseInt(initialBalance);
parseInt takes in "string", however if initialBalance is already a number (not a numeric string) this appears to work as well.
I know this is a bit of an opinionated question, but I'm really looking for options because the screaming in my ears from the C# developer in me is getting deafening. :)