npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

selective-option

v0.2.0

Published

A simple selective option resolver

Downloads

1,503

Readme

Selective Option

CI NPM Version install size jsDelivr Libraries.io dependency status for GitHub repo Codecov Known Vulnerabilities

A simple selective option resolver

Version 0.1.0 is a complete rewrite. Please read the documentation before you consider to switch, many exports have been removed and new ones have been added. It is highly recommended to switch to 0.1.0, just read the documentation before you do.

In this page

Install

npm

npm install selective-option

yarn

yarn add selective-option

pnpm

pnpm add selective-option

CDN

jsDelivr

  • UMD
<script src="https://cdn.jsdelivr.net/npm/selective-option@latest/dist/umd/selective.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/selective-option@latest/dist/umd/selective.umd.min.js"></script>
  • ES Module
<script type="module">
  import selective from "https://cdn.jsdelivr.net/npm/selective-option@latest/dist/esm/selective.mjs";
</script>
<script type="module">
  import selective from "https://cdn.jsdelivr.net/npm/selective-option@latest/dist/esm/selective.min.mjs";
</script>

more options...

unpkg

  • UMD
<script src="https://unpkg.com/selective-option@latest/dist/umd/selective.umd.js"></script>
<script src="https://unpkg.com/selective-option@latest/dist/umd/selective.umd.min.js"></script>
  • ES Module
<script type="module">
  import selective from "https://unpkg.com/selective-option@latest/dist/esm/selective.mjs";
</script>
<script type="module">
  import selective from "https://unpkg.com/selective-option@latest/dist/esm/selective.min.mjs";
</script>

more options...

API

function createValueBasedResolver

Creates a value based resolver. It resolves input as valid value (V), null, undefined, FunctionOption or ObjectOption. It internally uses createValueResolver, createFunctionResolver and createObjectResolver to create a Resolver using createResolver. See the examples for more info.

function createValueBasedResolver<K extends string, S extends string, V, O extends string, D = V>(
  keys: readonly K[],
  isValidValue: TypeCheckFunction<V>,
  defaultValue: D,
  overrideKey: O,
  special?: SpecialKeys<S, K> | null | undefined,
): ValueBasedResolver<K, S | O, V, D>;
  • Arguments
    • keys: An array of string to be used as keys in the final Resolved object. They will also be used to validate keys if input is an object.
    • isValidValue: A function which returns wether or not a value is valid.
    • defaultValue: A valid value to be used as default in case the value is null or undefined.
    • overrideKey: A string to be used to detect the override key if the input is an object.
    • special: An optional object mapping special keys to multiple regular keys. They can be used as keys if the input is an object.

See TypeCheckFunction, SpecialKeys and ValueBasedResolver.

  • Example
const resolveNumber = createValueBasedResolver(
  ['a', 'b', 'c'] as const,
  (value: unknown): value is number => typeof value === 'number',
  0,
  'override',
  { ac: ['a', 'c'] },
);

resolveNumber(18); // set value { a: 18, b: 18, c: 18 }
resolveNumber(true); // Throws because true doesn't pass the test
resolveNumber({}); // default value { a: 0, b: 0, c: 0 }
resolveNumber({ override: 40 }); // overridden value { a: 40, b: 40, c: 40 }
resolveNumber({ override: 'string' }); // Throws because 'string' doesn't pass the test
resolveNumber({ b: 40 }); // default + set value { a: 0, b: 40 c: 0 }
resolveNumber({ c: [] }); // Throws because [] doesn't pass the test
resolveNumber({ ac: 40 }); // default + special set value { a: 40, b: 0 c: 40 }
resolveNumber({ override: 40, a: 12 }); // overridden + set value { a: 12, b: 40, c: 40 }
resolveNumber({ override: 40, ac: 12 }); // overridden + special set value { a: 12, b: 40, c: 12 }
// ... you get the idea...

function createBoolBasedResolver

Creates a boolean based resolver. It resolves input as valid value (V), boolean, null, undefined, FunctionOption, KeyOption or ObjectOption. It internally uses createValueResolver, createFunctionResolver, createKeyResolver, createKeyListResolver and createObjectResolver to create a Resolver using createResolver. See the examples for more info.

function createBoolBasedResolver<K extends string, S extends string, V, O extends string, D = V>(
  keys: readonly K[],
  isValidValue: AllowNullish<TypeCheckFunction<V>>,
  defaultValue: D,
  overrideKey: O,
  special?: SpecialKeys<S, K> | null | undefined,
): BoolBasedResolver<K, S, V | boolean, O, D>;
  • Arguments
    • keys: An array of string to be used as keys in the final Resolved object. They will also be used to validate positive keys and negative keys if input is a string or an array, and to validate keys if input is an object.
    • isValidValue: A function which returns wether or not a value is valid. Note that this function doesn't need to test for boolean values as they will be included by default. If pass null or undefined, it will only test for boolean values.
    • defaultValue: A valid value to be used as default in case the value is null or undefined.
    • overrideKey: A string to be used to detect the override key if the input is an object.
    • special: An optional object mapping special keys to multiple regular keys. They can be used as keys if the input is an object and as positive keys or negative keys if input is a string or an array.

See TypeCheckFunction, SpecialKeys and BoolBasedResolver.

  • Example
const resolve = createBoolBasedResolver(
  ['a', 'b', 'c'] as const,
  (value: unknown): value is ('yes' | 'not' | 'unknown') => {
    return ['yes', 'no', 'unknown'].includes(value as never);
  },
  'unknown',
  'default',
  { ab: ['a', 'b'] },
);

resolveEvenNumber(null); // default value { a: 'unknown', b: 'unknown', c: 'unknown' }
resolveEvenNumber('yes'); // set value { a: 'yes', b: 'yes', c: 'yes' }
resolveEvenNumber(17); // Throws because 17 doesn't pass the test
resolveEvenNumber('a'); // set key { a: true, b: false, c: false }
resolveEvenNumber('ab'); // set key { a: true, b: true, c: false }
resolveEvenNumber(['a', 'c']); // set key { a: true, b: false, c: true }
resolveEvenNumber(['a', 'b', 'c']); // set key { a: true, b: true, c: true }
resolveEvenNumber(['ab', 'c']); // set key { a: true, b: true, c: true }
resolveEvenNumber({}); // default value { a: 'unknown', b: 'unknown', c: 'unknown' }
resolveEvenNumber({ default: true }); // overridden value { a: true, b: true, c: true }
resolveEvenNumber({ default: 15 }); // Throws because 15 doesn't pass the test
resolveEvenNumber({ default: 'yes', a: true }); // overridden + set value { a: true, b: 'yes', c: 'yes' }
// ... you get the idea...

function createValueResolver

Creates a potential resolver function that resolves to the input value if it satisfies isValidValue function, or defaultValue if input is null or undefined. It returns undefined otherwise.

function createValueResolver<K extends string, V>(
  keys: readonly K[],
  isValidValue: TypeCheckFunction<V>,
  defaultValue: V,
): PotentialResolver<K, V>;
  • Arguments
    • keys: An array of string to be used as keys in the final Resolved object.
    • isValidValue: A function which returns wether or not a value is valid.
    • defaultValue: A value to be used as default in case the input value is null or undefined.

See TypeCheckFunction and PotentialResolver.

function createFunctionResolver

Creates a potential resolver function that resolves if the input value is a function. It returns undefined otherwise.

The input function will receive the result key as only argument. The value returned by the input function will be used as value for the specific result key if it satisfies isValidValue, if it's null or undefined, defaultValue will be used instead. It will throw otherwise. See example below...

function createFunctionResolver<K extends string, V, D = V>(
  keys: readonly K[],
  isValidValue: TypeCheckFunction<V>,
  defaultValue: D,
): PotentialResolver<K, V | D>;
  • Arguments

    • keys: An array of string to be used as keys in the final Resolved object.
    • isValidValue: A function which returns wether or not a value is valid.
    • defaultValue: A value to be used as default in case the input function returns null or undefined.
  • Example

const resolve = createFunctionResolver(['a', 'b', 'c'], isNumber, 'none');

resolve((key) => key === 'b' ? 40 : 10); // resolves to { a: 10, b: 40, c: 10 }
resolve((key) => key === 'a' ? null : 33); // resolves to { a: 'none', b: 33, c: 33 }

// function returning an invalid value will throw
resolve((key) => 40) // throws

// non function inputs will be ignored by this resolver
resolve(40) // resolves to undefined

See TypeCheckFunction and PotentialResolver.

function createKeyResolver

Creates a potential resolver function that resolves if the input value is a string and is present in keys array, or if it is one of the special object keys. It also resolves if input follow the PositiveKey or NegativeKey format. It returns undefined otherwise.

This key determines the result. A positive key means "only that key". A negative key means "all other keys but that one". See example.

function createKeyResolver<K extends string, S extends string>(
  keys: KeyList<K>,
  special?: SpecialKeys<S, K> | null | undefined,
): PotentialResolver<K, boolean>;
  • Arguments
    • keys: An array of string to be used as keys in the final Resolved object. They will also be used to validate positive keys or negative keys.
    • special: An optional object mapping special keys to multiple regular keys. These special keys can also be used as positive keys or negative keys.

See KeyList, SpecialKeys and PotentialResolver.

  • Example
const resolve = createKeyResolver<'a' | 'b' | 'c', 'd'>(
  ['a', 'b', 'c'],
  { d: ['a', 'c'] },
);

resolve('c'); // Resolves to { a: false, b: false, c: true }
resolve('b'); // Resolves to { a: false, b: true, c: false }

resolve('a') // Resolves to { a: true, b: false, c: false } ::: Only "a" is set
resolve('!a') // Resolves to { a: false, b: true, c: true } ::: Everything but "a" is set

resolve('d'); // Resolves to { a: true, b: false, c: true } ::: Only "a" & "c" is set
resolve('!d'); // Resolves to { a: false, b: true, c: false } ::: Everything but "a" & "c" is set

function createKeyListResolver

Creates a potential resolver function that resolves if the input value is an array of string and every string is present in keys array, or if it is one of the special object keys. It also resolves if any of the string in the array follow the PositiveKey or NegativeKey format. It returns undefined otherwise.

The keys will be processed in the order they were added. The first key in the array will determine the default result, and the rest will mutate the result accordingly. A positive first key means "only that key". A negative first key means "all other keys but that one". See example.

function createKeyListResolver<K extends string, S extends string>(
  keys: KeyList<K>,
  special?: SpecialKeys<S, K> | null | undefined,
): PotentialResolver<K, boolean>;

See KeyList, SpecialKeys and PotentialResolver.

  • Example
const resolve = createKeyListResolver<'a' | 'b' | 'c', 'd'>(
  ['a', 'b', 'c'],
  { d: ['a', 'c'] },
);

resolve([]); // Resolves to { a: false, b: false, c: false }
resolve(['a', 'b']); // Resolves to { a: true, b: true, c: false }

// The first item sets the default
resolve(['a']) // Resolves to { a: true, b: false, c: false } ::: Only "a" is set
resolve(['!a']) // Resolves to { a: false, b: true, c: true } ::: Everything but "a" is set

// Watch the items order!!!

resolve(['a', '!a']) // Resolves to { a: false, b: false, c: false }
// because...
// step1 - 'a' => { a: true, b: false, c: false }
// step2 - '!a' => { ...step1, a: false }
// return step2

resolve(['!a', 'a']) // Resolves to { a: true, b: true, c: true }
// because...
// step1 - '!a' => { a: false, b: true, c: true }
// step2 - 'a' => { ...step1, a: true }
// return step2

resolve(['d', '!c']); // Resolves to { a: true, b: false, c: false }
// because...
// step1 = 'd' => { a: true, b: false, c: true }
// step2 = '!c' => { ...step1, c: false }
// return step2

resolve(['!c', 'd']); // Resolves to { a: true, b: true, c: true }
// because...
// step1 '!c' => { a: true, b: true, c: false }
// step2 'd' => { ...step1, a: true, c: true }
// return step2

function createObjectResolver

Creates a potential resolver function that resolves if the input value is an object and it follows the ObjectOption format. It returns undefined otherwise.

function createObjectResolver<K extends string, S extends string, V, O extends string>(
  keys: KeyList<K>,
  isValidValue: TypeCheckFunction<V>,
  defaultValue: V,
  overrideKey: O,
  special?: SpecialKeys<S, K> | null | undefined,
): PotentialResolver<K, V>;
  • Arguments
    • keys: An array of string to be used as keys in the final Resolved object. They will also be used to validate input object keys.
    • isValidValue: A function which returns wether or not a value is valid.
    • defaultValue: A valid value to be used as default in case the value is null or undefined.
    • overrideKey: A string to be used to detect the override key if the input is an object.
    • special: An optional object mapping special keys to multiple regular keys. They can also be used as keys in input object.

See KeyList, TypeCheckFunction, SpecialKeys and PotentialResolver.

function createResolver

Creates a resolver base on a series of potential resolvers. I will iterate through every potential resolver until one resolves and return the Resolved object result. It will throw if no potential resolver resolves.

function createResolver<K extends string, V, I = unknown>(
  ...resolvers: Array<PotentialResolver<K, V>>
): Resolver<K, V, I>;

See PotentialResolver and Resolver.

function createResult

Creates a Resolved object. Used internally in every potential resolver function. It is exported in case you need to write your own potential resolver function.

function createResult<K extends string, V>(
  keys: KeyList<K>,
  value: V,
): Resolved<K, V>;
  • Arguments
    • keys: An array of string to be used as keys in the Resolved object.
    • value: A value to be assigned to every key in the Resolved object.

See KeyList and Resolved.

  • Example

Creating a Resolved object.

createResult(['a', 'b', 'c'], true); // { a: true, b: true, c: true }
createResult(['a', 'b', 'c'], 10); // { a: 10, b: 10, c: 10 }

DEPRECATION NOTICE

This function accepts a third argument as input object, this is deprecated now and will be removed in the future. To extend a previous result use the object spread operator or Object.assign.

/** @deprecated */
function createResult<K extends string, V>(
  keys: KeyList<K>,
  value: V,
  input?: Resolved<K, V>
): Resolved<K, V>;
  • Arguments

    • keys: An array of string to be used as keys in the Resolved object.
    • value: A value to be assigned to every key in the Resolved object.
    • input: An optional Resolved object to be used as base for the new Resolved object. This input object won't be modified, a new one will be created instead. If you pass an empty array as keys, the input object will be returned, unless input is null or undefined in which case a new empty object will be returned.
  • Example

Extending a previously created Resolved object (DEPRECATED).

const base = createResult(['a', 'b', 'c'], 0); // base = { a: 0, b: 0, c: 0 }
const result = createResult(['a', 'c'], 40, base); // { a: 40, b: 0, c: 40 }

To extend a previously create result use...

const base = createResult(['a', 'b', 'c'], 0); // base = { a: 0, b: 0, c: 0 }
const override = createResult(['a', 'c'], 40); // { a: 40, c: 40 }
const result = { ...base, ...override }; // { a: 40, b: 0, c: 40 };

Exported Types

type FunctionOption

A function to be called for every key in the the final Resolved object.

export type FunctionOption<K extends string, V> = (key: K) => V | null | undefined;

type SingleKeyOption

type SingleKeyOption<K extends string> = PositiveKey<K> | NegativeKey<K>;

See PositiveKey and NegativeKey. Used in type KeyListOption and KeyOption.

  • Example
function logKey(key: SingleKeyOption<'a' | 'b'>) {
  console.log(key);
}

logKey('a'); // OK
logKey('b'); // OK
logKey('!a'); // OK
logKey('!b'); // OK
logKey('-a'); // OK
logKey('-b'); // OK

logKey('x') // Type Error
logKey('z') // Type Error
logKey('!z') // Type Error

type KeyListOption

type KeyListOption<K extends string> = KeyList<SingleKeyOption<K>>;

See KeyList and SingleKeyOption. Used in type KeyOption.

  • Example
function logKeys(keys: KeyListOption<'a' | 'b'>) {
  console.log(keys);
}

logKeys(['a']); // OK
logKeys(['a', '!b']); // OK
logKeys(['b', '-a']); // OK
logKeys(['a', 'b', '-a']); // OK

logKeys(['x']) // Type Error
logKeys(['!z']) // Type Error
logKeys(['x', 'a']) // Type Error
logKeys(['a', '!z']) // Type Error

type KeyOption

type KeyOption<K extends string> = SingleKeyOption<K> | KeyListOption<K>;

See SingleKeyOption and KeyListOption. Used in type BoolBasedSelectiveOption.

  • Example
function logOption(option: KeyOption<'a' | 'b'>) {
  console.log(option);
}

logOption('a'); // OK
logOption('b'); // OK
logOption('!a'); // OK
logOption('-b'); // OK
logOption(['-b', 'a']); // OK
logOption(['-b', '!a']); // OK

logOption('z') // Type Error
logOption('!z') // Type Error
logOption(['!z']) // Type Error
logOption(['!z', 'a']) // Type Error

type ObjectOption

An object containing the keys defined by K | O and the values of V, null or undefined. It will be used by the PotentialResolver created by createObjectResolver in order to create a result using createResult.

type ObjectOption<K extends string, V> = Partial<Record<K, V | null | undefined>>;
  • Generics K: keys allowed in the input object. V: value type allowed inside input object.

Used in type ValueBasedSelectiveOption.

  • Example
function logOption(option: ObjectOption<'a' | 'b' | 'override', number>) {
  console.log(option);
}

logOption({}); // OK
logOption({ override: 10 }); // OK
logOption({ override: 10, a: 8 }); // OK
logOption({ a: 45 }); // OK
logOption({ a: 45, b: 10 }); // OK

logOption('z') // Type Error
logOption([]) // Type Error
logOption({ override: 'string' }) // Type Error
logOption({ override: 'string', b: 0 }) // Type Error
logOption({ a: 10, b: true }) // Type Error

type ValueBasedSelectiveOption

type ValueBasedSelectiveOption<K extends string, X extends string, V> =
  | V
  | null
  | undefined
  | ObjectOption<K | X, V>;
  • Generics K: keys allowed if the input is an object. V: value type allowed as input value and inside input if it's an object.

See ObjectOption. Used in type BoolBasedSelectiveOption and ValueBasedResolver.

type BoolBasedSelectiveOption

type BoolBasedSelectiveOption<K extends string, S extends string, V, O extends string> =
  | KeyOption<K | S>
  | ValueBasedSelectiveOption<K, S | O, V | boolean>;
  • Generics K: keys allowed as positive keys or negative keys, and as keys if input is an object. V: value type allowed as input value and inside input if it's an object. It will also allow boolean as valid value. O: key name allowed for the override key if input is an object.

See KeyOption and ValueBasedSelectiveOption. Used in type BoolBasedResolver.

type KeyList

An immutable list of keys.

type KeyList<K> = readonly K[];

Used in function createKeyResolver, createKeyListResolver, createObjectResolver, createResult and type SpecialKeys.

type SpecialKeys

An object mapping special keys to a list of regular keys.

type SpecialKeys<S extends string, K extends string> = Readonly<Record<S, KeyList<K>>>;

See type KeyList. Used in function createValueBasedResolver, createBoolBasedResolver, createKeyResolver, createKeyListResolver and createObjectResolver.

  • Example
type Country = 'american' | 'japanese';
type Car = 'chevrolet' | 'toyota' | 'suzuki' | 'ford';

const special: SpecialKeys<Country, Car> = {
  american: ['ford', 'chevrolet'],
  japanese: ['toyota', 'suzuki'],
};

type Resolved

type Resolved<K extends string, V> = Readonly<Record<K, V>>;

Used in function createResult and type PotentialResolver, Resolver.

type PotentiallyResolved

type PotentiallyResolved<K extends string, V> = Resolved<K, V> | null | undefined;

Used in type PotentialResolver.

type PotentialResolver

type PotentialResolver<K extends string, V> = (input: unknown) => PotentiallyResolved<K, V> | void;

See PotentiallyResolved. Used in function createValueResolver, createFunctionResolver, createKeyResolver, createKeyListResolver, createObjectResolver and createResolver.

type Resolver

type Resolver<K extends string, V, I> = (input: I) => Resolved<K, V>;

See Resolved. Used in function createResolver and type ValueBasedResolver and BoolBasedResolver.

type ValueBasedResolver

type ValueBasedResolver<K extends string, X extends string, V, D = V> = Resolver<K, V | D, ValueBasedSelectiveOption<K, X, V>>;

See Resolver and ValueBasedSelectiveOption. Used in function createValueBasedResolver.

type BoolBasedResolver

type BoolBasedResolver<K extends string, S extends string, V, O extends string, D = V> = Resolver<K, V | D | boolean, BoolBasedSelectiveOption<K, S, V, O>>;

See Resolver and BoolBasedSelectiveOption. Used in function createBoolBasedResolver.

Other Types

These are types which are not exported but help to understand some of the exported types.

type PositiveKey

A key name or a key name prefixed with a + sign.

type PositiveKey<K extends string> = K | `+${K}`;

Used in type SingleKeyOption.

type NegativeKey

A key name prefixed with a ! or - sign.

type NegativeKey<K extends string> = `!${K}` | `-${K}`;

Used in type SingleKeyOption.

type TypeCheckFunction

type TypeCheckFunction<V> = (input: unknown) => input is V;

Used in function createValueBasedResolver, createBoolBasedResolver, createValueResolver, createFunctionResolver and createObjectResolver.

  • Example
const isString: TypeCheckFunction<string> = (input) => {
  return typeof input === 'string';
};

const isRGB: TypeCheckFunction<'red' | 'green' | 'blue'> = (input) => {
  return ['red', 'green', 'blue'].includes(input as never);
}

License

MIT © 2020-2024 Manuel Fernández (@manferlo81)