UI Drafter

JavaScript
Types without TypeScript

by Eric Fortis

In addition to the data type, let’s validate with more precise constraints and convenient error messages. For example:

function updateCardDecimals(cardId, decimals) {
  isCard(cardId)
  isValidDecimal(decimals)
  setCard(cardId, CF.decimals, decimals)
}

For context, that function sets the number of decimals of the total of UI Drafter’s cards.

Update Decimals of the Formula Total

isCard

This function ensures that cardId is a validly formatted string, and it asserts the exists card in the collection.

function isCard(cardId) {
  if (!/^[a-z]+$/i.test(cardId) || !Object.hasOwn(_cards, cardId))
    throw new CardNotFound(cardId)
}

class CardNotFound extends ReferenceError {}

isValidDecimal

In addition to the integer check, it verifies its value is between the allowed numeric range.

function isValidDecimal(value) {
  if (!Number.isInteger(value)
     || value < 0
     || value > MAX_FRACTION_DIGITS)
      throw RangeError(`Invalid Decimal "${value}"`)
}

JavaScript Error Types

EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, AggregateError

Another Example

This function sends a Bad Request HTML response, when the number of fields in the payload, and their names, don’t match the expectation. Also, as the previous example, it checks the values beyond data type checks.

const AuthError = 1
const ValidationError = 2

const isId = value =>
  isString(value)
    && value.length === StandardIdCharLength
    && /^[\w-]*$/.test(value)

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)
    ))
      throw ValidationError

    if (!await passwordResetTokenExists(body.token, body.userId))
      throw AuthError

    // …
    sendOk(response)
  }

  catch (error) {
    switch (error) {
      case AuthError:
        sendUnauthorized(response)
        break

      case ValidationError:
        sendBadRequest(response)
        break

      default:
        sendInternalServerError(response)
    }
  }
}
function isString(value) {
  return isTypeOf('')(value)
}

function isTypeOf(example) {
  const egType = Object.prototype.toString.call(example)
  return val => Object.prototype.toString.call(val) === egType
}

Open Source

Check out this library: type-check

check('a', String)
check(100, Number)
check(new Int8Array([1, 2, 3]), Int8Array)

Sponsored by: