Skip to content

Commit 6e6e9d4

Browse files
authored
Merge pull request #16 from mojotech/em/const
Allow constant decoder to match constant arrays and objects
2 parents 1fbe837 + a710f83 commit 6e6e9d4

File tree

5 files changed

+52
-20
lines changed

5 files changed

+52
-20
lines changed

docs/classes/_decoder_.decoder.md

+13-9
Original file line numberDiff line numberDiff line change
@@ -386,15 +386,19 @@ Note that `constant('string to match')` returns a `Decoder<string>` which fails
386386

387387
Providing the type parameter is only necessary for type-literal strings and numbers, as detailed by this table:
388388

389-
| Decoder | Type |
390-
| ---------------------------- | ----------------- |
391-
| constant(true) | Decoder<true> |
392-
| constant(false) | Decoder<false> |
393-
| constant(null) | Decoder<null> |
394-
| constant('alaska') | Decoder<string> |
395-
| constant<'alaska'>('alaska') | Decoder<'alaska'> |
396-
| constant(50) | Decoder<number> |
397-
| constant<50>(50) | Decoder<50> |
389+
| Decoder | Type |
390+
| ---------------------------- | ---------------------|
391+
| constant(true) | Decoder<true> |
392+
| constant(false) | Decoder<false> |
393+
| constant(null) | Decoder<null> |
394+
| constant('alaska') | Decoder<string> |
395+
| constant<'alaska'>('alaska') | Decoder<'alaska'> |
396+
| constant(50) | Decoder<number> |
397+
| constant<50>(50) | Decoder<50> |
398+
| constant([1,2,3]) | Decoder<number[]> |
399+
| constant<[1,2,3]>([1,2,3]) | Decoder<[1,2,3]> |
400+
| constant({x: 't'}) | Decoder<{x: string}> |
401+
| constant<{x: 't'}>({x: 't'}) | Decoder<{x: 't'}> |
398402

399403
One place where this happens is when a type-literal is in an interface:
400404

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"colors": "^1.1.2",
6868
"cross-env": "^5.0.1",
6969
"jest": "^22.0.2",
70+
"lodash": "^4.17.5",
7071
"prettier": "^1.4.4",
7172
"rimraf": "^2.6.1",
7273
"rollup": "^0.53.0",

src/decoder.ts

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as Result from './result';
2+
const isEqual = require('lodash/isEqual'); // this syntax avoids TS1192
23

34
/**
45
* Information describing how json data failed to match a decoder.
@@ -177,15 +178,19 @@ export class Decoder<A> {
177178
* and numbers, as detailed by this table:
178179
*
179180
* ```
180-
* | Decoder | Type |
181-
* | ---------------------------- | ----------------- |
182-
* | constant(true) | Decoder<true> |
183-
* | constant(false) | Decoder<false> |
184-
* | constant(null) | Decoder<null> |
185-
* | constant('alaska') | Decoder<string> |
186-
* | constant<'alaska'>('alaska') | Decoder<'alaska'> |
187-
* | constant(50) | Decoder<number> |
188-
* | constant<50>(50) | Decoder<50> |
181+
* | Decoder | Type |
182+
* | ---------------------------- | ---------------------|
183+
* | constant(true) | Decoder<true> |
184+
* | constant(false) | Decoder<false> |
185+
* | constant(null) | Decoder<null> |
186+
* | constant('alaska') | Decoder<string> |
187+
* | constant<'alaska'>('alaska') | Decoder<'alaska'> |
188+
* | constant(50) | Decoder<number> |
189+
* | constant<50>(50) | Decoder<50> |
190+
* | constant([1,2,3]) | Decoder<number[]> |
191+
* | constant<[1,2,3]>([1,2,3]) | Decoder<[1,2,3]> |
192+
* | constant({x: 't'}) | Decoder<{x: string}> |
193+
* | constant<{x: 't'}>({x: 't'}) | Decoder<{x: 't'}> |
189194
* ```
190195
*
191196
*
@@ -234,7 +239,7 @@ export class Decoder<A> {
234239
static constant(value: any): Decoder<any> {
235240
return new Decoder(
236241
(json: any) =>
237-
json === value
242+
isEqual(json, value)
238243
? Result.ok(value)
239244
: Result.err({message: `expected ${JSON.stringify(value)}, got ${JSON.stringify(json)}`})
240245
);

test/json-decode.test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,28 @@ describe('constant', () => {
146146

147147
expect(decoder.run({x: null})).toEqual({ok: true, result: {x: null}});
148148
});
149+
150+
it('can decode a constant array', () => {
151+
type A = [1, 2, 3];
152+
const decoder: Decoder<A> = constant<A>([1, 2, 3]);
153+
154+
expect(decoder.run([1, 2, 3])).toEqual({ok: true, result: [1, 2, 3]});
155+
expect(decoder.run([1, 2, 3, 4])).toMatchObject({
156+
ok: false,
157+
error: {at: 'input', message: 'expected [1,2,3], got [1,2,3,4]'}
158+
});
159+
});
160+
161+
it('can decode a constant object', () => {
162+
type O = {a: true; b: 12};
163+
const decoder: Decoder<O> = constant<O>({a: true, b: 12});
164+
165+
expect(decoder.run({a: true, b: 12})).toEqual({ok: true, result: {a: true, b: 12}});
166+
expect(decoder.run({a: true, b: 7})).toMatchObject({
167+
ok: false,
168+
error: {at: 'input', message: 'expected {"a":true,"b":12}, got {"a":true,"b":7}'}
169+
});
170+
});
149171
});
150172

151173
describe('object', () => {

yarn.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ lodash.sortby@^4.7.0:
19171917
version "4.7.0"
19181918
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
19191919

1920-
lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.4:
1920+
lodash@^4.13.1, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.17.5:
19211921
version "4.17.5"
19221922
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
19231923

0 commit comments

Comments
 (0)