From a64e860833ffac530ea8810b966baa95bc215643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 1 Jul 2019 15:46:45 +0200 Subject: [PATCH] feat(testlab): improve typings for `toJSON()` helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let the compiler understand toJSON's behavior for commonly used union types like `object | null` or `unknown[] | null`. Signed-off-by: Miroslav Bajtoš --- .../src/__tests__/unit/to-json.test.ts | 46 +++++++++++++++++++ packages/testlab/src/to-json.ts | 15 ++++++ 2 files changed, 61 insertions(+) diff --git a/packages/testlab/src/__tests__/unit/to-json.test.ts b/packages/testlab/src/__tests__/unit/to-json.test.ts index a1fd82c37cb7..1d85df4d7924 100644 --- a/packages/testlab/src/__tests__/unit/to-json.test.ts +++ b/packages/testlab/src/__tests__/unit/to-json.test.ts @@ -62,6 +62,42 @@ describe('toJSON', () => { expectUndefined(value); }); + it('handles `object | null`', () => { + const input = createValueOfUnionType({}); + const output = toJSON(input); + expectComplexType(output, input); + }); + + it('handles `object | undefined`', () => { + const input = createValueOfUnionType({}); + const output = toJSON(input); + expectComplexType(output, input); + }); + + it('handles `object | null | undefined`', () => { + const input = createValueOfUnionType({}); + const output = toJSON(input); + expectComplexType(output, input); + }); + + it('handles `unknown[] | null`', () => { + const input = createValueOfUnionType([]); + const output = toJSON(input); + expectComplexType(output, input); + }); + + it('handles `unknown[] | undefined`', () => { + const input = createValueOfUnionType([]); + const output = toJSON(input); + expectComplexType(output, input); + }); + + it('handles `unknown[] | null | undefined`', () => { + const input = createValueOfUnionType([]); + const output = toJSON(input); + expectComplexType(output, input); + }); + it('handles classes with custom toJSON', () => { class Customer { private __data: object; @@ -156,3 +192,13 @@ function expectNull(actual: null) { function expectUndefined(actual: undefined) { expect(actual).to.be.undefined(); } + +function expectComplexType(actual: T, expected: T) { + expect(actual).to.deepEqual(expected); +} + +// A helper to force TypeScript to treat the given value as of a union type, +// e.g. treat `{}` as `object | undefined | null`. +function createValueOfUnionType(value: T): T { + return value; +} diff --git a/packages/testlab/src/to-json.ts b/packages/testlab/src/to-json.ts index caf06b1ececf..8013dffc372c 100644 --- a/packages/testlab/src/to-json.ts +++ b/packages/testlab/src/to-json.ts @@ -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(value: T) { return JSON.parse(JSON.stringify({value})).value; }