Gathering detailed insights and metrics for io-ts-extra
Gathering detailed insights and metrics for io-ts-extra
Gathering detailed insights and metrics for io-ts-extra
Gathering detailed insights and metrics for io-ts-extra
@cinderlex/io-ts-types-extra
Additional codecs for use with io-ts
@taktikorg/unde-animi-omnis
<p align="center"> <a href="https://www.npmjs.com/package/@taktikorg/unde-animi-omnis"><img src="https://img.shields.io/npm/v/@taktikorg/unde-animi-omnis"></a> <a href=""><img src="https://img.shields.io/github/actions/workflow/status/RemiMyrset/@taktikor
@teamteanpm2024/aperiam-fugit-error
security holding package
@npmteam2024/pariatur-fuga-deserunt
[![github actions][actions-image]][actions-url] [![coverage][codecov-image]][codecov-url] [![dependency status][deps-svg]][deps-url] [![dev dependency status][dev-deps-svg]][dev-deps-url] [![License][license-image]][license-url] [![Downloads][downloads-im
npm install io-ts-extra
Typescript
Module System
Node Version
NPM Version
memorable-moniker v0.5.1
Updated on Oct 16, 2021
expect-type v0.13.0
Updated on Oct 16, 2021
fs-syncer v0.3.6
Updated on Oct 16, 2021
io-ts-extra v0.11.6
Updated on Oct 16, 2021
eslint-plugin-codegen v0.16.1
Updated on Oct 16, 2021
eslint-plugin-codegen v0.15.0
Updated on Jun 29, 2021
TypeScript (88.89%)
JavaScript (10.59%)
Shell (0.52%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
Apache-2.0 License
151 Stars
465 Commits
8 Forks
2 Watchers
47 Branches
9 Contributors
Updated on Jul 28, 2024
Latest Version
0.11.6
Package Id
io-ts-extra@0.11.6
Unpacked Size
127.15 kB
Size
29.12 kB
File Count
45
NPM Version
6.14.15
Node Version
12.22.6
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
6
Adds pattern matching, optional properties, and several other helpers and types, to io-ts.
The maintainers of io-ts are (rightly) strict about keeping the API surface small and manageable, and the implementation clean. As a result, io-ts is a powerful but somewhat low-level framework.
This library implements some higher-level concepts for use in real-life applications with complex requirements - combinators, utilities, parsers, reporters etc.
io-ts-types exists for similar reasons. This library will aim to be orthogonal to io-ts-types, and avoid re-inventing the wheel by exposing types that already exist there.
io-ts-extra will also aim to provide more high-level utilities and combinators than pre-defined codecs.
Philosophically, this library will skew slightly more towards pragmatism at the expense of type soundness - for example the stance on t.refinement vs t.brand.
This package is also less mature. It's currently in v0, so will have a different release cadence than io-ts-types.
Match an object against a number of cases. Loosely based on Scala's pattern matching.
1// get a value which could be a string or a number: 2const value = Math.random() < 0.5 ? 'foo' : Math.random() * 10 3const stringified = match(value) 4 .case(String, s => `the message is ${s}`) 5 .case(7, () => 'exactly seven') 6 .case(Number, n => `the number is ${n}`) 7 .get()
Under the hood, io-ts is used for validation. The first argument can be a "shorthand" for a type, but you can also pass in io-ts codecs directly for more complex types:
1// get a value which could be a string or a number: 2const value = Math.random() < 0.5 ? 'foo' : 123 3const stringified = match(value) 4 .case(t.number, n => `the number is ${n}`) 5 .case(t.string, s => `the message is ${s}`) 6 .get()
you can use a predicate function or t.refinement
for the equivalent of scala's case x: Int if x > 2
:
1// value which could be a string, or a real number in [0, 10): 2const value = Math.random() < 0.5 ? 'foo' : Math.random() * 10 3const stringified = match(value) 4 .case(Number, n => n > 2, n => `big number: ${n}`) 5 .case(Number, n => `small number: ${n}`) 6 .default(x => `not a number: ${x}`) 7 .get()
1// value which could be a string, or a real number in [0, 10): 2const value = Math.random() < 0.5 ? 'foo' : Math.random() * 10 3const stringified = match(value) 4 .case(t.refinement(t.number, n => n > 2), n => `big number: ${n}`) 5 .case(t.number, n => `small number: ${n}`) 6 .default(x => `not a number: ${x}`) 7 .get()
note: when using predicates or t.refinement
, the type being refined is not considered exhaustively matched, so you'll usually need to add a non-refined option, or you can also use .default
as a fallback case (the equivalent of .case(t.any, ...)
)
name | description |
---|---|
obj | the object to be pattern-matched |
Like @see match but no object is passed in when constructing the case statements. Instead .get
is a function into which a value should be passed.
1const Email = t.type({sender: t.string, subject: t.string, body: t.string}) 2const SMS = t.type({from: t.string, content: t.string}) 3const Message = t.union([Email, SMS]) 4type Message = typeof Message._A 5 6const content = matcher<MessageType>() 7 .case(SMS, s => s.content) 8 .case(Email, e => e.subject + '\n\n' + e.body) 9 .get({from: '123', content: 'hello'}) 10 11expect(content).toEqual('hello')
The function returned by .get
is stateless and has no this
context, you can store it in a variable and pass it around:
1const getContent = matcher<Message>() 2 .case(SMS, s => s.content) 3 .case(Email, e => e.subject + '\n\n' + e.body) 4 .get 5 6const allMessages: Message[] = getAllMessages(); 7const contents = allMessages.map(getContent);
The "shorthand" format for type specifications maps to io-ts types as follows:
Gets an io-ts codec from a shorthand input:
shorthand | io-ts type |
---|---|
String , Number , Boolean | t.string , t.number , t.boolean |
Literal raw strings, numbers and booleans e.g. 7 or 'foo' | t.literal(7) , t.literal('foo') etc. |
Regexes e.g. /^foo/ | see regexp |
null and undefined | t.null and t.undefined |
No input (not the same as explicitly passing undefined ) | t.unknown |
Objects e.g. { foo: String, bar: { baz: Number } } | t.type(...) e.g. t.type({foo: t.string, bar: t.type({ baz: t.number }) }) |
Array | t.unknownArray |
Object | t.object |
One-element arrays e.g. [String] | t.array(...) e.g. t.array(t.string) |
Tuples with explicit length e.g. [2, [String, Number]] | t.tuple e.g. t.tuple([t.string, t.number]) |
io-ts codecs | unchanged |
Unions, intersections, partials, tuples with more than 3 elements, and other complex types | not supported, except by passing in an io-ts codec |
Can be used much like t.type
from io-ts, but any property types wrapped with optional
from this package need not be supplied. Roughly equivalent to using t.intersection
with t.type
and t.partial
.
1const Person = sparseType({ 2 name: t.string, 3 age: optional(t.number), 4}) 5 6// no error - `age` is optional 7const bob: typeof Person._A = { name: 'bob' }
name | description |
---|---|
props | equivalent to the props passed into t.type |
a type with props
field, so the result can be introspected similarly to a type built with
t.type
or t.partial
- which isn't the case if you manually use t.intersection([t.type({...}), t.partial({...})])
unions the passed-in type with null
and undefined
.
A helper for building "parser-decoder" types - that is, types that validate an input, transform it into another type, and then validate the target type.
1const StringsFromMixedArray = mapper( 2 t.array(t.any), 3 t.array(t.string), 4 mixedArray => mixedArray.filter(value => typeof value === 'string') 5) 6StringsFromMixedArray.decode(['a', 1, 'b', 2]) // right(['a', 'b']) 7StringsFromMixedArray.decode('not an array') // left(...)
name | description |
---|---|
from | the expected type of input value |
to | the expected type of the decoded value |
map | transform (decode) a from type to a to type |
unmap | transfrom a to type back to a from type |
A helper for parsing strings into other types. A wrapper around mapper
where the from
type is t.string
.
1const IntFromString = parser(t.Int, parseFloat) 2IntFromString.decode('123') // right(123) 3IntFromString.decode('123.4') // left(...) 4IntFromString.decode('not a number') // left(...) 5IntFromString.decode(123) // left(...)
name | description |
---|---|
type | the target type |
decode | transform a string into the target type |
encode | transform the target type back into a string |
Like t.type
, but fails when any properties not specified in props
are defined.
1const Person = strict({name: t.string, age: t.number}) 2 3expectRight(Person.decode({name: 'Alice', age: 30})) 4expectLeft(Person.decode({name: 'Bob', age: 30, unexpectedProp: 'abc'})) 5expectRight(Person.decode({name: 'Bob', age: 30, unexpectedProp: undefined}))
name | description |
---|---|
props | dictionary of properties, same as the input to t.type |
name | optional type name |
note:
undefined
are permitted.sparseType
is used, so optional properties are supported.Like io-ts's refinement type but:
Context
to the predicate argument, so you can check parent key names etc.1const CloudResources = narrow( 2 t.type({ 3 database: t.type({username: t.string, password: t.string}), 4 service: t.type({dbConnectionString: t.string}), 5 }), 6 ({database}) => t.type({ 7 service: t.type({dbConnectionString: t.literal(`${database.username}:${database.password}`)}), 8 }) 9) 10 11const valid = CloudResources.decode({ 12 database: {username: 'user', password: 'pass'}, 13 service: {dbConnectionString: 'user:pass'}, 14}) 15// returns a `Right` 16 17const invalid = CloudResources.decode({ 18 database: {username: 'user', password: 'pass'}, 19 service: {dbConnectionString: 'user:wrongpassword'}, 20}) 21// returns a `Left` - service.dbConnectionString expected "user:pass", but got "user:wrongpassword"
Similar to io-ts's PathReporter, but gives slightly less verbose output.
name | description |
---|---|
validation | Usually the result of calling .decode with an io-ts codec. |
typeAlias | io-ts type names can be verbose. If the type you're using doesn't have a name, you can use this to keep error messages shorter. |
A type which validates its input as a string, then decodes with String.prototype.match
, succeeding with the RegExpMatchArray result if a match is found, and failing if no match is found.
1const AllCaps = regexp(/\b([A-Z]+)\b/) 2AllCaps.decode('HELLO') // right([ 'HELLO', index: 0, input: 'HELLO' ]) 3AllCaps.decode('hello') // left(...) 4AllCaps.decode(123) // left(...)
Validates that a value is an instance of a class using the instanceof
operator
1const DateType = instanceOf(Date) 2DateType.is(new Date()) // right(Date(...)) 3DateType.is('abc') // left(...)
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 3/27 approved changesets -- score normalized to 1
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
dangerous workflow patterns detected
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
32 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More