Types in plain JavaScript
Typed languages are fine, as far as they go. But unless the type system is Turing complete, type correctness cannot imply program correctness. — Uncle Bob
Let’s explore how we can validate types and constraints with
convenient error messages. For example, in TypeScript we would String
check cardId
and Number check decimals
,
which is fine, but we could take it a step further.
function updateCardDecimals(cardId, decimals) { isCard(cardId) isValidDecimal(decimals) setCard(cardId, CF.decimals, decimals) }
For context, that function is for formatting Uxtly’s formulas.
isCard
Let’s ensure that cardId
is a
validly formatted string, and assert the card exists in the collection.
function isCard(cardId) { if (!/^[a-z]+$/i.test(cardId) || !Object.hasOwn(cardsCollection, cardId)) throw new CardNotFound(cardId) } class CardNotFound extends ReferenceError {}
isValidDecimal
In addition to the integer check, we can verify that the value is in the allowed numeric range.
function isValidDecimal(value) { if (!Number.isInteger(value) || value < 0 || value > MAX_FRACTION_DIGITS) throw RangeError(`Invalid Decimal "${value}"`) }
BTW, the JavaScript Error Types:
EvalError
,
RangeError
,
ReferenceError
,
SyntaxError
,
TypeError
,
URIError
,
AggregateError
Server Side Example
The following function responds with Bad Request HTML when the number of fields in the payload, or their names don’t match the expectation. Also, it examines the values beyond their data type.
async function resetPasswordPost(request, response) { try { const body = await jsonBody(request) if (!( body && Object.keys(body).length === 3 && isPassword(body.password) && isId(body.userId) && isId(body.token) )) { Send.BadRequest(response) return } if (!await passwordResetTokenExists(body.token, body.userId)) { Send.Unauthorized(response) return } // … Send.Ok(response) } catch (error) { Send.InternalServerError(response, error) } }
function isId(value) { return check(value, String) && value.length === StandardIdCharLength && /^[\w-]*$/.test(value) }
Open Source
Check out this library: type-check
check('a', String) check(100, Number) check(new Int8Array([1, 2, 3]), Int8Array)