From 9a2f84806ea0443c477868cd09470c6a70afed84 Mon Sep 17 00:00:00 2001 From: jkomyno Date: Tue, 27 Apr 2021 20:44:34 +0200 Subject: [PATCH 1/2] Added test for too-broad validator return type --- tests/basics.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/basics.test.ts b/tests/basics.test.ts index 86202d4..5c3a655 100644 --- a/tests/basics.test.ts +++ b/tests/basics.test.ts @@ -117,6 +117,24 @@ test('choices field', () => { expect(() => cleanEnv({ FOO: 'hi' }, { FOO: str({ choices: 123 }) }, makeSilent)).toThrow() }) +test('choices typed', () => { + type Spec = { + NODE_ENV: 'production' | 'test' | 'development' + } + + const environment = { + NODE_ENV: 'test', + } + + const spec: Spec = cleanEnv(environment, { + NODE_ENV: str({ + choices: ['production', 'test', 'development'], + }), + }) + + expect(spec.NODE_ENV).toEqual('test') +}) + test('misconfigured spec', () => { // Validation throws with different error if spec is invalid // @ts-expect-error This misuse should be a type error From f6c55bebd478150778166c4133a5321d3371fafa Mon Sep 17 00:00:00 2001 From: jkomyno Date: Tue, 27 Apr 2021 20:45:34 +0200 Subject: [PATCH 2/2] validators: coerced return types to T to fix #139 --- src/validators.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/validators.ts b/src/validators.ts index 4e24910..6c36ae1 100644 --- a/src/validators.ts +++ b/src/validators.ts @@ -42,12 +42,12 @@ export function bool(spec?: Spec) { case 'true': case 't': case '1': - return true + return true as T case false: case 'false': case 'f': case '0': - return false + return false as T default: throw new EnvError(`Invalid bool input: "${input}"`) } @@ -58,20 +58,20 @@ export function num(spec?: Spec) { return makeValidator((input: string) => { const coerced = +input if (Number.isNaN(coerced)) throw new EnvError(`Invalid number input: "${input}"`) - return coerced + return coerced as T })(spec) } export function str(spec?: Spec) { return makeValidator((input: string) => { - if (typeof input === 'string') return input + if (typeof input === 'string') return input as T throw new EnvError(`Not a string: "${input}"`) })(spec) } export function email(spec?: Spec) { return makeValidator((x: string) => { - if (EMAIL_REGEX.test(x)) return x + if (EMAIL_REGEX.test(x)) return x as T throw new EnvError(`Invalid email address: "${x}"`) })(spec) } @@ -81,7 +81,7 @@ export function host(spec?: Spec) { if (!isFQDN(input) && !isIP(input)) { throw new EnvError(`Invalid host (domain or ip): "${input}"`) } - return input + return input as T })(spec) } @@ -97,7 +97,7 @@ export function port(spec?: Spec) { ) { throw new EnvError(`Invalid port input: "${input}"`) } - return coerced + return coerced as T })(spec) } @@ -105,7 +105,7 @@ export function url(spec?: Spec) { return makeValidator((x: string) => { try { new URL(x) - return x + return x as T } catch (e) { throw new EnvError(`Invalid url: "${x}"`) } @@ -121,7 +121,7 @@ export function url(spec?: Spec) { export function json(spec?: Spec) { return makeValidator((x: string) => { try { - return JSON.parse(x) + return JSON.parse(x) as T } catch (e) { throw new EnvError(`Invalid json: "${x}"`) }