sindresorhus / is

Type check values
MIT License
1.68k stars 109 forks source link

Proposal: is.propertyKey(value) #136

Closed PopGoesTheWza closed 3 years ago

PopGoesTheWza commented 3 years ago

Just a handy type guard of the PropertyKey persuasion...

else I'll do with the lazy implementation:

const isPropertyKey = (value: unknown): value is PropertyKey => is.any([is.string, is.number, is.symbol], value);
sindresorhus commented 3 years ago

How would you use it in a real-world scenario? (Code example)

PopGoesTheWza commented 3 years ago

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)

PopGoesTheWza commented 3 years ago

More generally, is.propertyKey can be useful to sanitize (and type guard) unknown values to be used with Reflect. methods like get and set.

sindresorhus commented 3 years ago

Makes sense. Pull request welcome :)