Best Practices
Alex Ewerlöf edited this page Jun 25, 2021
·
1 revision
- Every value should be validated close to where it is used. This usually means that the functions should validate the parameters that the logic in their own body depends on. This means the errors are going to have a better stack trace but also isolates the knowledge about the type requirements to the implementation that depends on it which makes refactoring easier.
- ALWAYS validate the shape and values of any input from external systems (users, other servers, even local JSON files that are not validated against a schema and/or don't live in the same repo as your code)
- If you're using TypeScript, use type guards to programmatically ensure the shape of a value (particularly objects)
- If you are writing TypeScript code that is going to be called from JavaScript, always verify the input of the user-facing APIs
- Use JavaScript's own language constructs whenever it makes sense
-
['possibleValue1', 'possibleValue2'].includes(x)
to check ifx
is any of the possible values (kinda like TypeScript's union types) -
someArray.every(item => checkItemFormat(item))
to check that all elements of an array have a certain shape -
isStr(x) || isInt(x)
check OR to ensure that a value is of either types -
a instanceOf A
ensure thata
is an instance of the classA
- Use the
in
operator with caution:user in objectWithOneKeyPerUser
returnstrue
if theuser
is'constructor'
(usehasOProp()
instead) - Use
console.assert()
in the browser orassert()
in Node. (note thatconsole.assert()
does not terminate the code execution)
-
- Don't check the shape of objects that are guaranteed to have a certain form. For example in
function f(...props) { if (Array.isArr(props)) ... }
,props
is guaranteed to be an array per JavaScript language specification. - If a function merely forwards a parameter to an inner function where it's used, it's best to validate the parameter in the inner function.
- A good error message should have enough information to facilitate inspection and troubleshooting.
- When throwing an error, use an appropriate JavaScript standard
Error
subclass:-
TypeError
when a value has an unexpected type -
ReferenceError
when a property is missing from an object -
RangeError
when a value is outside the expected range -
SyntaxError
when there is a syntax error (usually comes handy when parsing a string, using regular expressions or validating JSON) - You can also extend the relevant error class to create your own error:
class MyDomainSpecificError extends SyntaxError { constructor(...params) { super(...params) } /* ... */ }
- See more Error types on MDN
-