From ff59c8b389431f7bf55556b761e71993d9a28b35 Mon Sep 17 00:00:00 2001 From: gcanti Date: Wed, 21 Oct 2020 17:15:42 +0200 Subject: [PATCH] Experimental: make `sum` safer, closes #523 --- CHANGELOG.md | 28 +++++++++++++++++++++++++++- Decoder.md | 21 +++++++++++++++++++++ docs/modules/Decoder.ts.md | 2 +- docs/modules/Eq.ts.md | 4 +++- docs/modules/Guard.ts.md | 2 +- docs/modules/Schemable.ts.md | 10 +++++++--- docs/modules/TaskDecoder.ts.md | 2 +- docs/modules/Type.ts.md | 2 +- dtslint/ts3.5/Codec.ts | 10 ++++++---- dtslint/ts3.5/Decoder.ts | 10 ++++++---- dtslint/ts3.5/Eq.ts | 12 ++++++++++++ dtslint/ts3.5/Guard.ts | 12 ++++++++++++ dtslint/ts3.5/Schema.ts | 2 ++ dtslint/ts3.5/TaskDecoder.ts | 13 +++++++++++++ dtslint/ts3.5/tslint.json | 9 ++++++++- package-lock.json | 24 ++++++++++++------------ package.json | 4 ++-- src/Codec.ts | 2 +- src/Decoder.ts | 4 ++-- src/Eq.ts | 4 +++- src/Guard.ts | 2 +- src/Kleisli.ts | 2 +- src/Schemable.ts | 10 +++++++--- src/TaskDecoder.ts | 4 ++-- src/Type.ts | 5 +++-- test/Arbitrary.ts | 2 +- test/Decoder.ts | 26 +++++++++++++------------- test/Guard.ts | 10 +++++----- 28 files changed, 174 insertions(+), 64 deletions(-) create mode 100644 dtslint/ts3.5/TaskDecoder.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 78c2c6cc..7990f678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,9 +14,35 @@ **Note**: Gaps between patch versions are faulty/broken releases. **Note**: A feature tagged as Experimental is in a high state of flux, you're at risk of it changing without notice. +# 2.2.12 + +- **Experimental** + - (\*) make `sum` safer, closes #523 (@gcanti) + +(\*) breaking change + +In case of non-`string` tag values, the respective key must be enclosed in brackets + +```ts +export const MySum: D.Decoder< + unknown, + | { + type: 1 // non-`string` tag value + a: string + } + | { + type: 2 // non-`string` tag value + b: number + } +> = D.sum('type')({ + [1]: D.type({ type: D.literal(1), a: D.string }), + [2]: D.type({ type: D.literal(2), b: D.number }) +}) +``` + # 2.2.11 -- **Polish** +- **Experimental** - `Decoder` - make `toForest` stack-safe, #520 (@safareli) diff --git a/Decoder.md b/Decoder.md index f254119a..96e0d499 100644 --- a/Decoder.md +++ b/Decoder.md @@ -224,6 +224,27 @@ export const MySum: D.Decoder< }) ``` +**non-`string` tag values** + +In case of non-`string` tag values, the respective key must be enclosed in brackets + +```ts +export const MySum: D.Decoder< + unknown, + | { + type: 1 // non-`string` tag value + a: string + } + | { + type: 2 // non-`string` tag value + b: number + } +> = D.sum('type')({ + [1]: D.type({ type: D.literal(1), a: D.string }), + [2]: D.type({ type: D.literal(2), b: D.number }) +}) +``` + ## The `union` combinator The `union` combinator describes untagged unions diff --git a/docs/modules/Decoder.ts.md b/docs/modules/Decoder.ts.md index e4df5bee..dc7255a8 100644 --- a/docs/modules/Decoder.ts.md +++ b/docs/modules/Decoder.ts.md @@ -358,7 +358,7 @@ Added in v2.2.7 ```ts export declare const sum: ( tag: T -) => (members: { [K in keyof A]: Decoder }) => Decoder +) => (members: { [K in keyof A]: Decoder> }) => Decoder ``` Added in v2.2.7 diff --git a/docs/modules/Eq.ts.md b/docs/modules/Eq.ts.md index 35fddadf..7c23c1f9 100644 --- a/docs/modules/Eq.ts.md +++ b/docs/modules/Eq.ts.md @@ -112,7 +112,9 @@ Added in v2.2.2 **Signature** ```ts -export declare function sum(tag: T): (members: { [K in keyof A]: Eq }) => Eq +export declare function sum( + tag: T +): (members: { [K in keyof A]: Eq> }) => Eq ``` Added in v2.2.2 diff --git a/docs/modules/Guard.ts.md b/docs/modules/Guard.ts.md index 5671e7ca..72caf923 100644 --- a/docs/modules/Guard.ts.md +++ b/docs/modules/Guard.ts.md @@ -171,7 +171,7 @@ Added in v2.2.0 ```ts export declare const sum: ( tag: T -) => (members: { [K in keyof A]: Guard }) => Guard +) => (members: { [K in keyof A]: Guard> }) => Guard ``` Added in v2.2.0 diff --git a/docs/modules/Schemable.ts.md b/docs/modules/Schemable.ts.md index a4c9f09d..2f9aeef4 100644 --- a/docs/modules/Schemable.ts.md +++ b/docs/modules/Schemable.ts.md @@ -67,7 +67,9 @@ export interface Schemable { readonly array: (item: HKT) => HKT> readonly tuple: >(...components: { [K in keyof A]: HKT }) => HKT readonly intersect: (right: HKT) => (left: HKT) => HKT - readonly sum: (tag: T) => (members: { [K in keyof A]: HKT }) => HKT + readonly sum: ( + tag: T + ) => (members: { [K in keyof A]: HKT> }) => HKT readonly lazy: (id: string, f: () => HKT) => HKT } ``` @@ -92,7 +94,9 @@ export interface Schemable1 { readonly array: (item: Kind) => Kind> readonly tuple: >(...components: { [K in keyof A]: Kind }) => Kind readonly intersect: (right: Kind) => (left: Kind) => Kind - readonly sum: (tag: T) => (members: { [K in keyof A]: Kind }) => Kind + readonly sum: ( + tag: T + ) => (members: { [K in keyof A]: Kind> }) => Kind readonly lazy: (id: string, f: () => Kind) => Kind } ``` @@ -123,7 +127,7 @@ export interface Schemable2C { readonly intersect: (right: Kind2) => (left: Kind2) => Kind2 readonly sum: ( tag: T - ) => (members: { [K in keyof A]: Kind2 }) => Kind2 + ) => (members: { [K in keyof A]: Kind2> }) => Kind2 readonly lazy: (id: string, f: () => Kind2) => Kind2 } ``` diff --git a/docs/modules/TaskDecoder.ts.md b/docs/modules/TaskDecoder.ts.md index 0d7c789d..2ec9b094 100644 --- a/docs/modules/TaskDecoder.ts.md +++ b/docs/modules/TaskDecoder.ts.md @@ -361,7 +361,7 @@ Added in v2.2.7 ```ts export declare const sum: ( tag: T -) => (members: { [K in keyof A]: TaskDecoder }) => TaskDecoder +) => (members: { [K in keyof A]: TaskDecoder> }) => TaskDecoder ``` Added in v2.2.7 diff --git a/docs/modules/Type.ts.md b/docs/modules/Type.ts.md index 144d21cd..ec439c83 100644 --- a/docs/modules/Type.ts.md +++ b/docs/modules/Type.ts.md @@ -130,7 +130,7 @@ Added in v2.2.3 ```ts export declare const sum: ( _tag: T -) => (members: { [K in keyof A]: Type }) => Type +) => (members: { [K in keyof A]: Type> }) => Type ``` Added in v2.2.3 diff --git a/dtslint/ts3.5/Codec.ts b/dtslint/ts3.5/Codec.ts index d66bcee7..480c9746 100644 --- a/dtslint/ts3.5/Codec.ts +++ b/dtslint/ts3.5/Codec.ts @@ -106,8 +106,10 @@ _.fromSum('_tag')({ // sum // +const S1 = _.type({ _tag: _.literal('A'), a: _.string }) +const S2 = _.type({ _tag: _.literal('B'), b: _.number }) + // $ExpectType Codec -_.sum('_tag')({ - A: _.type({ _tag: _.literal('A'), a: _.string }), - B: _.type({ _tag: _.literal('B'), b: _.number }) -}) +_.sum('_tag')({ A: S1, B: S2 }) +// // $ExpectError +// _.sum('_tag')({ A: S1, B: S1 }) diff --git a/dtslint/ts3.5/Decoder.ts b/dtslint/ts3.5/Decoder.ts index ddcad509..ad43cff6 100644 --- a/dtslint/ts3.5/Decoder.ts +++ b/dtslint/ts3.5/Decoder.ts @@ -123,11 +123,13 @@ _.fromSum('_tag')({ // sum // +const S1 = _.type({ _tag: _.literal('A'), a: _.string }) +const S2 = _.type({ _tag: _.literal('B'), b: _.number }) + // $ExpectType Decoder -_.sum('_tag')({ - A: _.type({ _tag: _.literal('A'), a: _.string }), - B: _.type({ _tag: _.literal('B'), b: _.number }) -}) +_.sum('_tag')({ A: S1, B: S2 }) +// $ExpectError +_.sum('_tag')({ A: S1, B: S1 }) // // union diff --git a/dtslint/ts3.5/Eq.ts b/dtslint/ts3.5/Eq.ts index f41f379a..5e948dc0 100644 --- a/dtslint/ts3.5/Eq.ts +++ b/dtslint/ts3.5/Eq.ts @@ -15,3 +15,15 @@ _.partial({ c: _.number }) }) + +// +// sum +// + +const S1 = _.type({ _tag: _.Schemable.literal('A'), a: _.string }) +const S2 = _.type({ _tag: _.Schemable.literal('B'), b: _.number }) + +// $ExpectType Eq<{ _tag: "A"; a: string; } | { _tag: "B"; b: number; }> +_.sum('_tag')({ A: S1, B: S2 }) +// // $ExpectError +// _.sum('_tag')({ A: S1, B: S1 }) diff --git a/dtslint/ts3.5/Guard.ts b/dtslint/ts3.5/Guard.ts index 8ca9b88d..afc8a9a4 100644 --- a/dtslint/ts3.5/Guard.ts +++ b/dtslint/ts3.5/Guard.ts @@ -30,3 +30,15 @@ _.partial({ // $ExpectType { a: string; b: { c: number; }; } export type A = _.TypeOf + +// +// sum +// + +const S1 = _.type({ _tag: _.literal('A'), a: _.string }) +const S2 = _.type({ _tag: _.literal('B'), b: _.number }) + +// $ExpectType Guard +_.sum('_tag')({ A: S1, B: S2 }) +// $ExpectError +_.sum('_tag')({ A: S1, B: S1 }) diff --git a/dtslint/ts3.5/Schema.ts b/dtslint/ts3.5/Schema.ts index 7b8ff53d..921fd5a4 100644 --- a/dtslint/ts3.5/Schema.ts +++ b/dtslint/ts3.5/Schema.ts @@ -100,6 +100,8 @@ const S2 = make((S) => S.type({ _tag: S.literal('B'), b: S.number })) // $ExpectType Schema<{ _tag: "A"; a: string; } | { _tag: "B"; b: number; }> make((S) => S.sum('_tag')({ A: S1(S), B: S2(S) })) +// $ExpectError +make((S) => S.sum('_tag')({ A: S1(S), B: S1(S) })) // // lazy diff --git a/dtslint/ts3.5/TaskDecoder.ts b/dtslint/ts3.5/TaskDecoder.ts new file mode 100644 index 00000000..8d8af5d4 --- /dev/null +++ b/dtslint/ts3.5/TaskDecoder.ts @@ -0,0 +1,13 @@ +import * as _ from '../../src/TaskDecoder' + +// +// sum +// + +const S1 = _.type({ _tag: _.literal('A'), a: _.string }) +const S2 = _.type({ _tag: _.literal('B'), b: _.number }) + +// $ExpectType TaskDecoder +_.sum('_tag')({ A: S1, B: S2 }) +// $ExpectError +_.sum('_tag')({ A: S1, B: S1 }) diff --git a/dtslint/ts3.5/tslint.json b/dtslint/ts3.5/tslint.json index 9ce37507..1691e6c2 100644 --- a/dtslint/ts3.5/tslint.json +++ b/dtslint/ts3.5/tslint.json @@ -14,6 +14,13 @@ "object-literal-shorthand": false, "prefer-object-spread": false, "whitespace": false, - "use-default-type-parameter": false + "use-default-type-parameter": false, + "interface-name": false, + "no-promise-as-boolean": false, + "no-eval": false, + "label-position": false, + "function-constructor": false, + "invalid-void": false, + "no-construct": false } } diff --git a/package-lock.json b/package-lock.json index 5441c204..e9c61cac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "io-ts", - "version": "2.2.10", + "version": "2.2.12", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2125,7 +2125,7 @@ } }, "dtslint": { - "version": "github:gcanti/dtslint#de9181e0f1069b16ea15da87f74d88ed9bc221b7", + "version": "github:gcanti/dtslint#249e07696dbd4588287d320a705f0ad39175eeb6", "from": "github:gcanti/dtslint", "dev": true, "requires": { @@ -2133,7 +2133,7 @@ "parsimmon": "^1.12.0", "strip-json-comments": "^2.0.1", "tslint": "^5.12.0", - "typescript": "^4.0.0-dev.20200514" + "typescript": "^4.1.0-dev.20201021" }, "dependencies": { "fs-extra": { @@ -2169,9 +2169,9 @@ } }, "typescript": { - "version": "4.0.0-dev.20200514", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.0-dev.20200514.tgz", - "integrity": "sha512-o++Z0PwCL2iqEwTnoUVfDIAMo9xS+dvxm/6sl6n2VfxGGmVyaC9F6Naaylh+VZ5qG6Actdso0kJnzDxXVwY5fw==", + "version": "4.1.0-dev.20201021", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.0-dev.20201021.tgz", + "integrity": "sha512-AysECaeZgcDxcSDtzFq3hBwJ7cCG7md0gWBZIH19UPDcGtJBaAM6F/NCT4LZ4AV2NeGLQtEAGzE53lMq/i5whw==", "dev": true } } @@ -5646,9 +5646,9 @@ "dev": true }, "parsimmon": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.13.0.tgz", - "integrity": "sha512-5UIrOCW+gjbILkjKPgTgmq8LKf8TT3Iy7kN2VD7OtQ81facKn8B4gG1X94jWqXYZsxG2KbJhrv/Yq/5H6BQn7A==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/parsimmon/-/parsimmon-1.16.0.tgz", + "integrity": "sha512-tekGDz2Lny27SQ/5DzJdIK0lqsWwZ667SCLFIDCxaZM7VNgQjyKLbaL7FYPKpbjdxNAXFV/mSxkq5D2fnkW4pA==", "dev": true }, "pascalcase": { @@ -7200,9 +7200,9 @@ } }, "typescript": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz", - "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", + "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", "dev": true }, "unc-path-regex": { diff --git a/package.json b/package.json index 0cd8f9fc..89b653ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "io-ts", - "version": "2.2.11", + "version": "2.2.12", "description": "TypeScript runtime type system for IO decoding/encoding", "main": "lib/index.js", "module": "es6/index.js", @@ -59,7 +59,7 @@ "ts-node": "8.8.2", "tslint": "6.1.1", "tslint-config-standard": "9.0.0", - "typescript": "^3.9.6" + "typescript": "^4.0.3" }, "tags": [ "typescript", diff --git a/src/Codec.ts b/src/Codec.ts index abbfbf32..301bcbe5 100644 --- a/src/Codec.ts +++ b/src/Codec.ts @@ -227,7 +227,7 @@ export function record(codomain: Codec): Codec>>( ...components: C ): Codec<{ [K in keyof C]: InputOf }, { [K in keyof C]: OutputOf }, { [K in keyof C]: TypeOf }> => - make(D.fromTuple(...components) as any, E.tuple(...components)) + make(D.fromTuple(...components) as any, E.tuple(...components)) as any /** * @category combinators diff --git a/src/Decoder.ts b/src/Decoder.ts index a44f78eb..1b510228 100644 --- a/src/Decoder.ts +++ b/src/Decoder.ts @@ -295,7 +295,7 @@ export const record = (codomain: Decoder): Decoder>>( ...components: C ): Decoder<{ [K in keyof C]: InputOf }, { [K in keyof C]: TypeOf }> => - K.fromTuple(M)((i, e) => FS.of(DE.index(i, DE.required, e)))(...components) + K.fromTuple(M)((i, e) => FS.of(DE.index(i, DE.required, e)))(...components) as any /** * @category combinators @@ -345,7 +345,7 @@ export const fromSum = (tag: T) => (tag: T) => ( - members: { [K in keyof A]: Decoder } + members: { [K in keyof A]: Decoder> } ): Decoder => pipe(UnknownRecord as any, compose(fromSum(tag)(members))) /** diff --git a/src/Eq.ts b/src/Eq.ts index 394a517f..49a4f257 100644 --- a/src/Eq.ts +++ b/src/Eq.ts @@ -145,7 +145,9 @@ export const intersect = (right: Eq) => (left: Eq): Eq => ({ * @category combinators * @since 2.2.2 */ -export function sum(tag: T): (members: { [K in keyof A]: Eq }) => Eq { +export function sum( + tag: T +): (members: { [K in keyof A]: Eq> }) => Eq { return (members: Record>) => { return { equals: (x: Record, y: Record) => { diff --git a/src/Guard.ts b/src/Guard.ts index 2d8c7792..9747db1c 100644 --- a/src/Guard.ts +++ b/src/Guard.ts @@ -218,7 +218,7 @@ export const union = ]>( * @since 2.2.0 */ export const sum = (tag: T) => ( - members: { [K in keyof A]: Guard } + members: { [K in keyof A]: Guard> } ): Guard => pipe( UnknownRecord, diff --git a/src/Kleisli.ts b/src/Kleisli.ts index b9ad7484..81e890ba 100644 --- a/src/Kleisli.ts +++ b/src/Kleisli.ts @@ -287,7 +287,7 @@ export function fromSum( const keys = Object.keys(members) return { decode: (ir) => { - const v = ir[tag] + const v: any = ir[tag] if (v in members) { return (members as any)[v].decode(ir) } diff --git a/src/Schemable.ts b/src/Schemable.ts index f5fc3929..967aff39 100644 --- a/src/Schemable.ts +++ b/src/Schemable.ts @@ -31,7 +31,9 @@ export interface Schemable { readonly array: (item: HKT) => HKT> readonly tuple: >(...components: { [K in keyof A]: HKT }) => HKT readonly intersect: (right: HKT) => (left: HKT) => HKT - readonly sum: (tag: T) => (members: { [K in keyof A]: HKT }) => HKT + readonly sum: ( + tag: T + ) => (members: { [K in keyof A]: HKT> }) => HKT readonly lazy: (id: string, f: () => HKT) => HKT } @@ -51,7 +53,9 @@ export interface Schemable1 { readonly array: (item: Kind) => Kind> readonly tuple: >(...components: { [K in keyof A]: Kind }) => Kind readonly intersect: (right: Kind) => (left: Kind) => Kind - readonly sum: (tag: T) => (members: { [K in keyof A]: Kind }) => Kind + readonly sum: ( + tag: T + ) => (members: { [K in keyof A]: Kind> }) => Kind readonly lazy: (id: string, f: () => Kind) => Kind } @@ -77,7 +81,7 @@ export interface Schemable2C { readonly intersect: (right: Kind2) => (left: Kind2) => Kind2 readonly sum: ( tag: T - ) => (members: { [K in keyof A]: Kind2 }) => Kind2 + ) => (members: { [K in keyof A]: Kind2> }) => Kind2 readonly lazy: (id: string, f: () => Kind2) => Kind2 } diff --git a/src/TaskDecoder.ts b/src/TaskDecoder.ts index d8ef66dc..33cef914 100644 --- a/src/TaskDecoder.ts +++ b/src/TaskDecoder.ts @@ -299,7 +299,7 @@ export const record = (codomain: TaskDecoder): TaskDecoder>>( ...components: C ): TaskDecoder<{ [K in keyof C]: InputOf }, { [K in keyof C]: TypeOf }> => - K.fromTuple(M)((i, e) => FS.of(DE.index(i, DE.required, e)))(...components) + K.fromTuple(M)((i, e) => FS.of(DE.index(i, DE.required, e)))(...components) as any /** * @category combinators @@ -351,7 +351,7 @@ export const fromSum = (tag: T) => (tag: T) => ( - members: { [K in keyof A]: TaskDecoder } + members: { [K in keyof A]: TaskDecoder> } ): TaskDecoder => pipe(UnknownRecord as any, compose(fromSum(tag)(members))) /** diff --git a/src/Type.ts b/src/Type.ts index ca08b5ec..744cf72a 100644 --- a/src/Type.ts +++ b/src/Type.ts @@ -144,8 +144,9 @@ export const lazy = (id: string, f: () => Type): Type => t.recursion(id * @category combinators * @since 2.2.3 */ -export const sum = (_tag: T) => (members: { [K in keyof A]: Type }): Type => - t.union(Object.values(members) as any) +export const sum = (_tag: T) => ( + members: { [K in keyof A]: Type> } +): Type => t.union(Object.values(members) as any) /** * @category combinators diff --git a/test/Arbitrary.ts b/test/Arbitrary.ts index c195d023..ab300229 100644 --- a/test/Arbitrary.ts +++ b/test/Arbitrary.ts @@ -84,7 +84,7 @@ export const intersect = (right: Arbitrary) => (left: Arbitrary): Ar export function sum( _tag: T -): (members: { [K in keyof A]: Arbitrary }) => Arbitrary { +): (members: { [K in keyof A]: Arbitrary> }) => Arbitrary { return (members: Record>) => fc.oneof(...Object.keys(members).map((k) => members[k])) } diff --git a/test/Decoder.ts b/test/Decoder.ts index c23f6dbe..55b34e65 100644 --- a/test/Decoder.ts +++ b/test/Decoder.ts @@ -262,19 +262,6 @@ describe('Decoder', () => { ) ) }) - - it('should support getters', async () => { - class A { - get a() { - return 'a' - } - get b() { - return 'b' - } - } - const decoder = _.partial({ a: _.string, b: _.string }) - assert.deepStrictEqual(decoder.decode(new A()), _.success({ a: 'a', b: 'b' })) - }) }) describe('array', () => { @@ -483,6 +470,19 @@ describe('Decoder', () => { E.left(FS.of(DE.key('_tag', DE.required, FS.of(DE.leaf(undefined, 'never'))))) ) }) + + it('should support non-`string` tag values', () => { + const decoder = _.sum('_tag')({ + [1]: _.type({ _tag: _.literal(1), a: _.string }), + [2]: _.type({ _tag: _.literal(2), b: _.number }) + }) + assert.deepStrictEqual(decoder.decode({ _tag: 1, a: 'a' }), E.right({ _tag: 1, a: 'a' })) + assert.deepStrictEqual(decoder.decode({ _tag: 2, b: 1 }), E.right({ _tag: 2, b: 1 })) + assert.deepStrictEqual( + decoder.decode({ _tag: 2, b: 'a' }), + E.left(FS.of(DE.key('b', DE.required, FS.of(DE.leaf('a', 'number'))))) + ) + }) }) interface A { diff --git a/test/Guard.ts b/test/Guard.ts index 5034563b..0ae0887b 100644 --- a/test/Guard.ts +++ b/test/Guard.ts @@ -273,12 +273,12 @@ describe('Guard', () => { it('should support non-`string` tag values', () => { const guard = G.sum('_tag')({ - true: G.type({ _tag: G.literal(true), a: G.string }), - false: G.type({ _tag: G.literal(false), b: G.number }) + [1]: G.type({ _tag: G.literal(1), a: G.string }), + [2]: G.type({ _tag: G.literal(2), b: G.number }) }) - assert.deepStrictEqual(guard.is({ _tag: true, a: 'a' }), true) - assert.deepStrictEqual(guard.is({ _tag: false, b: 1 }), true) - assert.deepStrictEqual(guard.is({ _tag: false, b: 'a' }), false) + assert.deepStrictEqual(guard.is({ _tag: 1, a: 'a' }), true) + assert.deepStrictEqual(guard.is({ _tag: 2, b: 1 }), true) + assert.deepStrictEqual(guard.is({ _tag: 2, b: 'a' }), false) }) }) })