selective-option v0.2.0
Selective Option
A simple selective option resolver
Version
0.1.0is 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 to0.1.0, just read the documentation before you do.
In this page
- Install
- CDN
- API
- Resolvers
- function
createValueBasedResolver - function
createBoolBasedResolver
- function
- Potential Resolvers
- function
createValueResolver - function
createFunctionResolver - function
createKeyResolver - function
createKeyListResolver - function
createObjectResolver
- function
- Others
- function
createResolver - function
createResult
- function
- Resolvers
- Exported Types
- Input Types
- type
FunctionOption - type
SingleKeyOption - type
KeyListOption - type
KeyOption - type
ObjectOption - type
ValueBasedSelectiveOption - type
BoolBasedSelectiveOption
- type
- Resolver related Types
- type
KeyList - type
SpecialKeys - type
Resolved - type
PotentiallyResolved - type
PotentialResolver - type
Resolver - type
ValueBasedResolver - type
BoolBasedResolver
- type
- Input Types
- Other Types
- type
PositiveKey - type
NegativeKey - type
TypeCheckFunction
- type
Install
npm
npm install selective-optionyarn
yarn add selective-optionpnpm
pnpm add selective-optionCDN
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>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>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: Anarrayofstringto be used askeysin the finalResolvedobject. They will also be used to validatekeysif input is anobject.isValidValue: Afunctionwhich returns wether or not avalueisvalid.defaultValue: Avalidvalueto be used as default in case the value isnullorundefined.overrideKey: Astringto be used to detect theoverride keyif the input is anobject.special: An optional object mappingspecial keysto multipleregular keys. They can be used askeysif the input is anobject.
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: Anarrayofstringto be used askeysin the finalResolvedobject. They will also be used to validatepositive keysandnegative keysif input is astringor anarray, and to validatekeysif input is anobject.isValidValue: Afunctionwhich returns wether or not avalueisvalid. Note that this function doesn't need to test forbooleanvalues as they will be included by default. If passnullorundefined, it will only test forbooleanvalues.defaultValue: Avalidvalueto be used as default in case the value isnullorundefined.overrideKey: Astringto be used to detect theoverride keyif the input is anobject.special: An optional object mappingspecial keysto multipleregular keys. They can be used askeysif the input is anobjectand aspositive keysornegative keysif input is astringor anarray.
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: Anarrayofstringto be used askeysin the finalResolvedobject.isValidValue: Afunctionwhich returns wether or not avalueisvalid.defaultValue: Avalueto be used as default in case the input value isnullorundefined.
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: Anarrayofstringto be used askeysin the finalResolvedobject.isValidValue: Afunctionwhich returns wether or not avalueisvalid.defaultValue: Avalueto be used as default in case the input function returnsnullorundefined.
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 undefinedSee 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: Anarrayofstringto be used askeysin the finalResolvedobject. They will also be used to validatepositive keysornegative keys.special: An optional object mappingspecial keysto multipleregular keys. Thesespecial keyscan also be used aspositive keysornegative 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 setfunction 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 step2function 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: Anarrayofstringto be used askeysin the finalResolvedobject. They will also be used to validate input objectkeys.isValidValue: Afunctionwhich returns wether or not avalueisvalid.defaultValue: Avalidvalueto be used as default in case the value isnullorundefined.overrideKey: Astringto be used to detect theoverride keyif the input is anobject.special: An optional object mappingspecial keysto multipleregular keys. They can also be used askeysin inputobject.
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
- 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: Anarrayofstringto be used askeysin theResolvedobject.value: A value to be assigned to everykeyin theResolvedobject.input: An optionalResolvedobject to be used as base for the newResolvedobject. Thisinputobject won't be modified, a new one will be created instead. If you pass an empty array askeys, the input object will be returned, unlessinputisnullorundefinedin which case a new emptyobjectwill 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 Errortype 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 Errortype 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 Errortype 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:keysallowed in the inputobject.V:valuetype allowed inside inputobject.
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 Errortype ValueBasedSelectiveOption
type ValueBasedSelectiveOption<K extends string, X extends string, V> =
| V
| null
| undefined
| ObjectOption<K | X, V>;- Generics
K:keysallowed if the input is anobject.V:valuetype allowed as input value and inside input if it's anobject.
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:keysallowed aspositive keysornegative keys, and as keys if input is anobject.V:valuetype allowed as input value and inside input if it's anobject. It will also allowbooleanas valid value.O:keyname allowed for theoverridekey if input is anobject.
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)