selective-option
v0.2.0
Published
A simple selective option resolver
Downloads
1,503
Maintainers
Readme
Selective Option
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 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-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>
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
: Anarray
ofstring
to be used askeys
in the finalResolved
object. They will also be used to validatekeys
if input is anobject
.isValidValue
: Afunction
which returns wether or not avalue
isvalid
.defaultValue
: Avalid
value
to be used as default in case the value isnull
orundefined
.overrideKey
: Astring
to be used to detect theoverride key
if the input is anobject
.special
: An optional object mappingspecial keys
to multipleregular keys
. They can be used askeys
if 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
: Anarray
ofstring
to be used askeys
in the finalResolved
object. They will also be used to validatepositive keys
andnegative keys
if input is astring
or anarray
, and to validatekeys
if input is anobject
.isValidValue
: Afunction
which returns wether or not avalue
isvalid
. Note that this function doesn't need to test forboolean
values as they will be included by default. If passnull
orundefined
, it will only test forboolean
values.defaultValue
: Avalid
value
to be used as default in case the value isnull
orundefined
.overrideKey
: Astring
to be used to detect theoverride key
if the input is anobject
.special
: An optional object mappingspecial keys
to multipleregular keys
. They can be used askeys
if the input is anobject
and aspositive keys
ornegative keys
if input is astring
or 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
: Anarray
ofstring
to be used askeys
in the finalResolved
object.isValidValue
: Afunction
which returns wether or not avalue
isvalid
.defaultValue
: Avalue
to be used as default in case the input value isnull
orundefined
.
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
: Anarray
ofstring
to be used askeys
in the finalResolved
object.isValidValue
: Afunction
which returns wether or not avalue
isvalid
.defaultValue
: Avalue
to be used as default in case the input function returnsnull
orundefined
.
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
: Anarray
ofstring
to be used askeys
in the finalResolved
object. They will also be used to validatepositive keys
ornegative keys
.special
: An optional object mappingspecial keys
to multipleregular keys
. Thesespecial keys
can also be used aspositive keys
ornegative 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
: Anarray
ofstring
to be used askeys
in the finalResolved
object. They will also be used to validate input objectkeys
.isValidValue
: Afunction
which returns wether or not avalue
isvalid
.defaultValue
: Avalid
value
to be used as default in case the value isnull
orundefined
.overrideKey
: Astring
to be used to detect theoverride key
if the input is anobject
.special
: An optional object mappingspecial keys
to multipleregular keys
. They can also be used askeys
in 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
: Anarray
ofstring
to be used askeys
in theResolved
object.value
: A value to be assigned to everykey
in theResolved
object.input
: An optionalResolved
object to be used as base for the newResolved
object. Thisinput
object won't be modified, a new one will be created instead. If you pass an empty array askeys
, the input object will be returned, unlessinput
isnull
orundefined
in which case a new emptyobject
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 inputobject
.V
:value
type 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 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 anobject
.V
:value
type 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
:keys
allowed aspositive keys
ornegative keys
, and as keys if input is anobject
.V
:value
type allowed as input value and inside input if it's anobject
. It will also allowboolean
as valid value.O
:key
name allowed for theoverride
key 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)