Skip to content

Commit

Permalink
feat(testlab): improve typings for toJSON() helper
Browse files Browse the repository at this point in the history
Let the compiler understand toJSON's behavior for commonly used
union types like `object | null` or `unknown[] | null`.

Signed-off-by: Miroslav Bajtoš <[email protected]>
  • Loading branch information
bajtos committed Jul 1, 2019
1 parent de29df6 commit 6b25603
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
48 changes: 48 additions & 0 deletions packages/testlab/src/__tests__/unit/to-json.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,50 @@ describe('toJSON', () => {
expectUndefined(value);
});

it('handles `object | null`', () => {
const input: object | null = Math.random() ? {} : null;
const output = toJSON(input);
expectComplexType<object | null>(output, input);
});

it('handles `object | undefined`', () => {
const input: object | undefined = Math.random() ? {} : undefined;
const output = toJSON(input);
expectComplexType<object | undefined>(output, input);
});

it('handles `object | null | undefined`', () => {
const input: object | null | undefined = Math.random()
? {}
: Math.random()
? null
: undefined;
const output = toJSON(input);
expectComplexType<object | null | undefined>(output, input);
});

it('handles `unknown[] | null`', () => {
const input: unknown[] | null = Math.random() ? [] : null;
const output = toJSON(input);
expectComplexType<unknown[] | null>(output, input);
});

it('handles `unknown[] | undefined`', () => {
const input: unknown[] | undefined = Math.random() ? [] : undefined;
const output = toJSON(input);
expectComplexType<unknown[] | undefined>(output, input);
});

it('handles `unknown[] | null | undefined`', () => {
const input: unknown[] | null | undefined = Math.random()
? []
: Math.random()
? null
: undefined;
const output = toJSON(input);
expectComplexType<unknown[] | null | undefined>(output, input);
});

it('handles classes with custom toJSON', () => {
class Customer {
private __data: object;
Expand Down Expand Up @@ -156,3 +200,7 @@ function expectNull(actual: null) {
function expectUndefined(actual: undefined) {
expect(actual).to.be.undefined();
}

function expectComplexType<T>(actual: T, expected: T) {
expect(actual).to.deepEqual(expected);
}
15 changes: 15 additions & 0 deletions packages/testlab/src/to-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ export function toJSON(value: number): number;
export function toJSON(value: boolean): boolean;
export function toJSON(value: string): string;

// The following overloads are required to allow TypesScript handle
// commonly used union types.

export function toJSON(value: unknown[] | null): unknown[] | null;
export function toJSON(value: unknown[] | undefined): unknown[] | undefined;
export function toJSON(
value: unknown[] | null | undefined,
): unknown[] | null | undefined;

export function toJSON(value: object | null): object | null;
export function toJSON(value: object | undefined): object | undefined;
export function toJSON(
value: object | null | undefined,
): object | null | undefined;

export function toJSON<T>(value: T) {
return JSON.parse(JSON.stringify({value})).value;
}

0 comments on commit 6b25603

Please sign in to comment.