Closed PopGoesTheWza closed 3 years ago
How would you use it in a real-world scenario? (Code example)
The need came as I was playing around porting this SO answer to Typescript:
import is from '@sindresorhus/is';
type Key = PropertyKey | PropertyKey[] | ((key: PropertyKey) => unknown);
type Value = PropertyKey | Result;
type Case = [Key, Value];
export type Cases = Case[];
export type Result = () => unknown;
export const switchF = (value: PropertyKey, options: Cases, defaultValue: Result): unknown => {
const choice = options.find(([key]) =>
is.array(key) ? key.includes(value) : is.function_(key) ? key(value) : key === value
);
const resolve = ([, value]: Case) =>
is.function_(value) ? value() : isPropertyKey(value) ? switchF(value, options, defaultValue) : throwError();
return choice ? resolve(choice) : defaultValue();
};
const isPropertyKey = (value: unknown): value is PropertyKey => is.any([is.string, is.number, is.symbol], value);
const throwError = (): never => {
throw new Error('switch F failed!');
};
The idea is a FP-friendly (and arguably over designed) 'switch case', where cases are expressed as an array of [Key, Value]
tuples. Long story short, a Value
is either a function returning the result or a new Key
to lookup for... Hence inside the resolve
function we check the value with the isPropertyKey
helper (and nifty type guard)
More generally, is.propertyKey
can be useful to sanitize (and type guard) unknown values to be used with Reflect.
methods like get
and set
.
Makes sense. Pull request welcome :)
Just a handy type guard of the
PropertyKey
persuasion...else I'll do with the lazy implementation: