123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /**
- * @callback Handler
- * Handle a value, with a certain ID field set to a certain value.
- * The ID field is passed to `zwitch`, and it’s value is this function’s
- * place on the `handlers` record.
- * @param {...any} parameters
- * Arbitrary parameters passed to the zwitch.
- * The first will be an object with a certain ID field set to a certain value.
- * @returns {any}
- * Anything!
- */
- /**
- * @callback UnknownHandler
- * Handle values that do have a certain ID field, but it’s set to a value
- * that is not listed in the `handlers` record.
- * @param {unknown} value
- * An object with a certain ID field set to an unknown value.
- * @param {...any} rest
- * Arbitrary parameters passed to the zwitch.
- * @returns {any}
- * Anything!
- */
- /**
- * @callback InvalidHandler
- * Handle values that do not have a certain ID field.
- * @param {unknown} value
- * Any unknown value.
- * @param {...any} rest
- * Arbitrary parameters passed to the zwitch.
- * @returns {void|null|undefined|never}
- * This should crash or return nothing.
- */
- /**
- * @template {InvalidHandler} [Invalid=InvalidHandler]
- * @template {UnknownHandler} [Unknown=UnknownHandler]
- * @template {Record<string, Handler>} [Handlers=Record<string, Handler>]
- * @typedef Options
- * Configuration (required).
- * @property {Invalid} [invalid]
- * Handler to use for invalid values.
- * @property {Unknown} [unknown]
- * Handler to use for unknown values.
- * @property {Handlers} [handlers]
- * Handlers to use.
- */
- const own = {}.hasOwnProperty
- /**
- * Handle values based on a field.
- *
- * @template {InvalidHandler} [Invalid=InvalidHandler]
- * @template {UnknownHandler} [Unknown=UnknownHandler]
- * @template {Record<string, Handler>} [Handlers=Record<string, Handler>]
- * @param {string} key
- * Field to switch on.
- * @param {Options<Invalid, Unknown, Handlers>} [options]
- * Configuration (required).
- * @returns {{unknown: Unknown, invalid: Invalid, handlers: Handlers, (...parameters: Parameters<Handlers[keyof Handlers]>): ReturnType<Handlers[keyof Handlers]>, (...parameters: Parameters<Unknown>): ReturnType<Unknown>}}
- */
- export function zwitch(key, options) {
- const settings = options || {}
- /**
- * Handle one value.
- *
- * Based on the bound `key`, a respective handler will be called.
- * If `value` is not an object, or doesn’t have a `key` property, the special
- * “invalid” handler will be called.
- * If `value` has an unknown `key`, the special “unknown” handler will be
- * called.
- *
- * All arguments, and the context object, are passed through to the handler,
- * and it’s result is returned.
- *
- * @this {unknown}
- * Any context object.
- * @param {unknown} [value]
- * Any value.
- * @param {...unknown} parameters
- * Arbitrary parameters passed to the zwitch.
- * @property {Handler} invalid
- * Handle for values that do not have a certain ID field.
- * @property {Handler} unknown
- * Handle values that do have a certain ID field, but it’s set to a value
- * that is not listed in the `handlers` record.
- * @property {Handlers} handlers
- * Record of handlers.
- * @returns {unknown}
- * Anything.
- */
- function one(value, ...parameters) {
- /** @type {Handler|undefined} */
- let fn = one.invalid
- const handlers = one.handlers
- if (value && own.call(value, key)) {
- // @ts-expect-error Indexable.
- const id = String(value[key])
- // @ts-expect-error Indexable.
- fn = own.call(handlers, id) ? handlers[id] : one.unknown
- }
- if (fn) {
- return fn.call(this, value, ...parameters)
- }
- }
- one.handlers = settings.handlers || {}
- one.invalid = settings.invalid
- one.unknown = settings.unknown
- // @ts-expect-error: matches!
- return one
- }
|