Skip to content

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 if x 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 that a is an instance of the class A
    • Use the in operator with caution: user in objectWithOneKeyPerUser returns true if the user is 'constructor' (use hasOProp() instead)
    • Use console.assert() in the browser or assert() in Node. (note that console.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
Clone this wiki locally