Skip to content

dictionary()

ts
function dictionary<K, V>(parseKey, parseValue): Parser<string extends K ? Record<K, V> : Partial<Record<K, V>>>

Dictionaries are objects that map strings to other values.

Due to how TypeScript works, this function has two behaviors at the type level, depending on Key (At runtime, it always behaves the same):

  • When the key is string, it validates Record<string, V>. When noUncheckedIndexedAccess is enabled, TypeScript understands that a value retrieved with a string the value can be undefined. However, the value is not semantically identical to Partial<Record<string, V>>.
  • When the key is a subset of string, it validates Partial<Record<K, V>>. If the properties were not marked as optional, TypeScript would assume that all keys map to values.

Type Parameters

Type Parameter
K extends string
V

Parameters

ParameterTypeDescription
parseKeyParser<K>parses every key
parseValueParser<V>parses every value

Returns

Parser<string extends K ? Record<K, V> : Partial<Record<K, V>>>

a parser for a record

Examples

Validate a dictionary:

ts
const parseDictionary = dictionary(isString, isString)
parseDictionary({ hello: 'world' }) // -> Success
parseDictionary({ hello: 1 }) // -> Failure

You can transform the keys and values; for example, to only allow lowercase strings:

ts
const parseLowerCase = (data: unknown): data is Lowercase<string> =>
  typeof data === 'string' ? failure('Not a string') : success(data.toLowerCase())
const parseDictionary = dictionary(parseLowerCase, parseLowerCase)
parseDictionary({ hello: 'world' }) // -> Success<{ hello: 'world' }>
parseDictionary({ Hello: 'world' }) // -> Success<{ hello: 'world' }>
parseDictionary({ hello: 'World' }) // -> Success<{ hello: 'world' }>