Skip to content

Commit

Permalink
refactor(experimental): support more scalar values in getDiscriminate…
Browse files Browse the repository at this point in the history
…dUnionCodec (#2395)

This PR changes the custom values supported by `getDiscriminatedUnionCodec` from:

```ts
type DiscriminatorValue = number | string | symbol;
```

to:

```ts
type DiscriminatorValue = bigint | boolean | number | string | null | undefined;
```

Note that:
- We are dropping the `symbol` type since TypeScript doesn't make any distinctions between different symbols (i.e. `Symbol('A') | Symbol('B')` is typed as `symbol | symbol`).
- These values are now consistent with the new `getLiteralUnionCodec`.
  • Loading branch information
lorisleiva authored Apr 2, 2024
1 parent 288029a commit 7f48706
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 4 deletions.
2 changes: 1 addition & 1 deletion packages/codecs-data-structures/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ messageCodec.encode({ message: 'Write', fields: ['Hi'] });
messageCodec.encode({ message: 'Move', x: 5, y: 6 });
```

Note that, the discriminator value of a variant may also be a `number`, `symbol` or a JavaScript `enum`. For instance, the following is also valid:
Note that, the discriminator value of a variant may be any scalar value — such as `number`, `bigint`, `boolean`, a JavaScript `enum`, etc. For instance, the following is also valid:

```ts
enum Message {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ describe('getDiscriminatedUnionCodec', () => {
expect(codec.read(b('002a'), 0)).toStrictEqual([{ __kind: 1, one: 42 }, 2]);
});

it('encodes discriminated unions with boolean discriminator values', () => {
const codec = discriminatedUnion([
[true, struct([['truth', u8()]])],
[false, struct([['lie', u32()]])],
]);
expect(codec.encode({ __kind: true, truth: 42 })).toStrictEqual(b('002a'));
expect(codec.read(b('002a'), 0)).toStrictEqual([{ __kind: true, truth: 42 }, 2]);
});

it('encodes discriminated unions with enum discriminator values', () => {
enum Event {
Click,
Expand Down
2 changes: 1 addition & 1 deletion packages/codecs-data-structures/src/discriminated-union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export type DiscriminatedUnionCodecConfig<
size?: TDiscriminatorSize;
};

type DiscriminatorValue = number | string | symbol;
type DiscriminatorValue = bigint | boolean | number | string | null | undefined;
type Variants<T> = readonly (readonly [DiscriminatorValue, T])[];
type ArrayIndices<T extends readonly unknown[]> = Exclude<Partial<T>['length'], T['length']> & number;

Expand Down
4 changes: 2 additions & 2 deletions packages/errors/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ export type SolanaErrorContext = DefaultUnspecifiedErrorContextToUndefined<
expected: number;
};
[SOLANA_ERROR__CODECS__INVALID_DISCRIMINATED_UNION_VARIANT]: {
value: number | string | symbol;
variants: (number | string | symbol)[];
value: bigint | boolean | number | string | null | undefined;
variants: readonly (bigint | boolean | number | string | null | undefined)[];
};
[SOLANA_ERROR__CODECS__INVALID_ENUM_VARIANT]: {
maxRange: number;
Expand Down

0 comments on commit 7f48706

Please sign in to comment.