Skip to content

Commit c2a813a

Browse files
author
Elias Mulhall
committed
Add unknownJson decoder
Previously `anyJson` was referred to as the identity decoder, but that's no longer accurate with the update to using `unknown`. I'm not sure how useful this is as a decoder, but it seems best to include for completeness sake.
1 parent 41c97d7 commit c2a813a

File tree

4 files changed

+47
-6
lines changed

4 files changed

+47
-6
lines changed

src/combinators.ts

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export const boolean = Decoder.boolean;
1414
/** See `Decoder.anyJson` */
1515
export const anyJson = Decoder.anyJson;
1616

17+
/** See `Decoder.unknownJson` */
18+
export const unknownJson: () => Decoder<unknown> = Decoder.unknownJson;
19+
1720
/** See `Decoder.constant` */
1821
export const constant = Decoder.constant;
1922

src/decoder.ts

+7
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,13 @@ export class Decoder<A> {
193193
*/
194194
static anyJson = (): Decoder<any> => new Decoder<any>((json: any) => Result.ok(json));
195195

196+
/**
197+
* Decoder identity function which always succeeds and types the result as
198+
* `unknown`.
199+
*/
200+
static unknownJson = (): Decoder<unknown> =>
201+
new Decoder<unknown>((json: unknown) => Result.ok(json));
202+
196203
/**
197204
* Decoder primitive that only matches on exact values.
198205
*

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export {
88
number,
99
boolean,
1010
anyJson,
11+
unknownJson,
1112
constant,
1213
object,
1314
array,

test/json-decode.test.ts

+36-6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
number,
77
boolean,
88
anyJson,
9+
unknownJson,
910
constant,
1011
object,
1112
array,
@@ -95,13 +96,42 @@ describe('boolean', () => {
9596
});
9697

9798
describe('anyJson', () => {
98-
it('can be used in other decoders', () => {
99-
const json: any = [1, true, 2, 3, 'five', 4, []];
100-
const jsonArray: any[] = Result.withDefault([], array(anyJson()).run(json));
101-
const successes: Result.Ok<number>[] = jsonArray.map(number().run).filter(Result.isOk);
102-
const numbers: number[] = successes.map(ok => ok.result);
99+
it('bypasses type validation', () => {
100+
// in a real use case this could be a deeply nested object
101+
type ComplexType = number;
103102

104-
expect(numbers).toEqual([1, 2, 3, 4]);
103+
interface User {
104+
name: string;
105+
complexUserData: ComplexType;
106+
}
107+
108+
const userDecoder: Decoder<User> = object({
109+
name: string(),
110+
complexUserData: anyJson()
111+
});
112+
113+
expect(userDecoder.run({name: 'Wanda', complexUserData: true})).toEqual({
114+
ok: true,
115+
result: {name: 'Wanda', complexUserData: true}
116+
});
117+
118+
expect(userDecoder.run({name: 'Willard', complexUserData: 'trash data'})).toEqual({
119+
ok: true,
120+
result: {name: 'Willard', complexUserData: 'trash data'}
121+
});
122+
123+
expect(userDecoder.run({name: 73, complexUserData: []})).toMatchObject({
124+
ok: false,
125+
error: {at: 'input.name', message: 'expected a string, got a number'}
126+
});
127+
});
128+
});
129+
130+
describe('unknownJson', () => {
131+
it('accepts any values', () => {
132+
expect(unknownJson().run(1)).toEqual({ok: true, result: 1});
133+
expect(unknownJson().run(false)).toEqual({ok: true, result: false});
134+
expect(unknownJson().run({boots: 'n cats'})).toEqual({ok: true, result: {boots: 'n cats'}});
105135
});
106136
});
107137

0 commit comments

Comments
 (0)