Skip to content

Commit

Permalink
Fix output type of optional, nullable and nullish #935
Browse files Browse the repository at this point in the history
  • Loading branch information
fabian-hiller committed Nov 22, 2024
1 parent 98a10f5 commit 532fbcb
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 4 deletions.
11 changes: 11 additions & 0 deletions library/src/schemas/nullable/nullable.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformAction } from '../../actions/index.ts';
import type { SchemaWithPipe } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -46,6 +48,12 @@ describe('nullable', () => {
type Schema3 = NullableSchema<StringSchema<undefined>, 'foo'>;
type Schema4 = NullableSchema<StringSchema<undefined>, () => null>;
type Schema5 = NullableSchema<StringSchema<undefined>, () => 'foo'>;
type Schema6 = NullableSchema<
SchemaWithPipe<
[StringSchema<undefined>, TransformAction<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | null;
Expand All @@ -54,6 +62,7 @@ describe('nullable', () => {
expectTypeOf<InferInput<Schema3>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema4>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema6>>().toEqualTypeOf<Input>();
});

test('of output', () => {
Expand All @@ -62,6 +71,7 @@ describe('nullable', () => {
expectTypeOf<InferOutput<Schema3>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema4>>().toEqualTypeOf<string | null>();
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema6>>().toEqualTypeOf<number>();
});

test('of issue', () => {
Expand All @@ -70,6 +80,7 @@ describe('nullable', () => {
expectTypeOf<InferIssue<Schema3>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema4>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema6>>().toEqualTypeOf<StringIssue>();
});
});
});
11 changes: 11 additions & 0 deletions library/src/schemas/nullable/nullableAsync.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformActionAsync } from '../../actions/index.ts';
import type { SchemaWithPipeAsync } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -66,6 +68,12 @@ describe('nullableAsync', () => {
StringSchema<undefined>,
() => Promise<'foo'>
>;
type Schema8 = NullableSchemaAsync<
SchemaWithPipeAsync<
[StringSchema<undefined>, TransformActionAsync<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | null;
Expand All @@ -76,6 +84,7 @@ describe('nullableAsync', () => {
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema6>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema7>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema8>>().toEqualTypeOf<Input>();
});

test('of output', () => {
Expand All @@ -86,6 +95,7 @@ describe('nullableAsync', () => {
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema6>>().toEqualTypeOf<string | null>();
expectTypeOf<InferOutput<Schema7>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema8>>().toEqualTypeOf<number>();
});

test('of issue', () => {
Expand All @@ -96,6 +106,7 @@ describe('nullableAsync', () => {
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema6>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema7>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema8>>().toEqualTypeOf<StringIssue>();
});
});
});
2 changes: 1 addition & 1 deletion library/src/schemas/nullable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export type InferNullableOutput<
TDefault extends DefaultAsync<TWrapped, null>,
> = undefined extends TDefault
? InferOutput<TWrapped> | null
: InferOutput<TWrapped> | DefaultValue<TDefault>;
: InferOutput<TWrapped> | Extract<DefaultValue<TDefault>, null>;
11 changes: 11 additions & 0 deletions library/src/schemas/nullish/nullish.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformAction } from '../../actions/index.ts';
import type { SchemaWithPipe } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -53,6 +55,12 @@ describe('nullish', () => {
type Schema4 = NullishSchema<StringSchema<undefined>, () => undefined>;
type Schema5 = NullishSchema<StringSchema<undefined>, () => null>;
type Schema6 = NullishSchema<StringSchema<undefined>, () => 'foo'>;
type Schema7 = NullishSchema<
SchemaWithPipe<
[StringSchema<undefined>, TransformAction<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | null | undefined;
Expand All @@ -62,6 +70,7 @@ describe('nullish', () => {
expectTypeOf<InferInput<Schema4>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema6>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema7>>().toEqualTypeOf<Input>();
});

test('of output', () => {
Expand All @@ -73,6 +82,7 @@ describe('nullish', () => {
expectTypeOf<InferOutput<Schema4>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<string | null>();
expectTypeOf<InferOutput<Schema6>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema7>>().toEqualTypeOf<number>();
});

test('of issue', () => {
Expand All @@ -82,6 +92,7 @@ describe('nullish', () => {
expectTypeOf<InferIssue<Schema4>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema6>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema7>>().toEqualTypeOf<StringIssue>();
});
});
});
11 changes: 11 additions & 0 deletions library/src/schemas/nullish/nullishAsync.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformActionAsync } from '../../actions/index.ts';
import type { SchemaWithPipeAsync } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -83,6 +85,12 @@ describe('nullishAsync', () => {
StringSchema<undefined>,
() => Promise<'foo'>
>;
type Schema10 = NullishSchemaAsync<
SchemaWithPipeAsync<
[StringSchema<undefined>, TransformActionAsync<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | null | undefined;
Expand All @@ -95,6 +103,7 @@ describe('nullishAsync', () => {
expectTypeOf<InferInput<Schema7>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema8>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema9>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema10>>().toEqualTypeOf<Input>();
});

test('of output', () => {
Expand All @@ -109,6 +118,7 @@ describe('nullishAsync', () => {
expectTypeOf<InferOutput<Schema7>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema8>>().toEqualTypeOf<string | null>();
expectTypeOf<InferOutput<Schema9>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema10>>().toEqualTypeOf<number>();
});

test('of issue', () => {
Expand All @@ -121,6 +131,7 @@ describe('nullishAsync', () => {
expectTypeOf<InferIssue<Schema7>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema8>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema9>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema10>>().toEqualTypeOf<StringIssue>();
});
});
});
2 changes: 1 addition & 1 deletion library/src/schemas/nullish/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export type InferNullishOutput<
TDefault extends DefaultAsync<TWrapped, null | undefined>,
> = undefined extends TDefault
? InferOutput<TWrapped> | null | undefined
: InferOutput<TWrapped> | DefaultValue<TDefault>;
: InferOutput<TWrapped> | Extract<DefaultValue<TDefault>, null | undefined>;
11 changes: 11 additions & 0 deletions library/src/schemas/optional/optional.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformAction } from '../../actions/index.ts';
import type { SchemaWithPipe } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -39,27 +41,36 @@ describe('optional', () => {
type Schema2 = OptionalSchema<StringSchema<undefined>, 'foo'>;
type Schema3 = OptionalSchema<StringSchema<undefined>, () => undefined>;
type Schema4 = OptionalSchema<StringSchema<undefined>, () => 'foo'>;
type Schema5 = OptionalSchema<
SchemaWithPipe<
[StringSchema<undefined>, TransformAction<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | undefined;
expectTypeOf<InferInput<Schema1>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema2>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema3>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema4>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
});

test('of output', () => {
expectTypeOf<InferOutput<Schema1>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema2>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema3>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema4>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<number>();
});

test('of issue', () => {
expectTypeOf<InferIssue<Schema1>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema2>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema3>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema4>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
});
});
});
11 changes: 11 additions & 0 deletions library/src/schemas/optional/optionalAsync.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformActionAsync } from '../../actions/index.ts';
import type { SchemaWithPipeAsync } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -64,6 +66,12 @@ describe('optionalAsync', () => {
StringSchema<undefined>,
() => Promise<'foo'>
>;
type Schema7 = OptionalSchemaAsync<
SchemaWithPipeAsync<
[StringSchema<undefined>, TransformActionAsync<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | undefined;
Expand All @@ -73,6 +81,7 @@ describe('optionalAsync', () => {
expectTypeOf<InferInput<Schema4>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema6>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema7>>().toEqualTypeOf<Input>();
});

test('of output', () => {
Expand All @@ -82,6 +91,7 @@ describe('optionalAsync', () => {
expectTypeOf<InferOutput<Schema4>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema6>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema7>>().toEqualTypeOf<number>();
});

test('of issue', () => {
Expand All @@ -91,6 +101,7 @@ describe('optionalAsync', () => {
expectTypeOf<InferIssue<Schema4>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema6>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema7>>().toEqualTypeOf<StringIssue>();
});
});
});
2 changes: 1 addition & 1 deletion library/src/schemas/optional/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export type InferOptionalOutput<
TDefault extends DefaultAsync<TWrapped, undefined>,
> = undefined extends TDefault
? InferOutput<TWrapped> | undefined
: InferOutput<TWrapped> | DefaultValue<TDefault>;
: InferOutput<TWrapped> | Extract<DefaultValue<TDefault>, undefined>;
2 changes: 1 addition & 1 deletion library/src/schemas/undefinedable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ export type InferUndefinedableOutput<
TDefault extends DefaultAsync<TWrapped, undefined>,
> = undefined extends TDefault
? InferOutput<TWrapped> | undefined
: InferOutput<TWrapped> | DefaultValue<TDefault>;
: InferOutput<TWrapped> | Extract<DefaultValue<TDefault>, undefined>;
11 changes: 11 additions & 0 deletions library/src/schemas/undefinedable/undefinedable.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformAction } from '../../actions/index.ts';
import type { SchemaWithPipe } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -42,27 +44,36 @@ describe('undefinedable', () => {
() => undefined
>;
type Schema4 = UndefinedableSchema<StringSchema<undefined>, () => 'foo'>;
type Schema5 = UndefinedableSchema<
SchemaWithPipe<
[StringSchema<undefined>, TransformAction<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | undefined;
expectTypeOf<InferInput<Schema1>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema2>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema3>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema4>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
});

test('of output', () => {
expectTypeOf<InferOutput<Schema1>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema2>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema3>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema4>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<number>();
});

test('of issue', () => {
expectTypeOf<InferIssue<Schema1>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema2>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema3>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema4>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
});
});
});
11 changes: 11 additions & 0 deletions library/src/schemas/undefinedable/undefinedableAsync.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expectTypeOf, test } from 'vitest';
import type { TransformActionAsync } from '../../actions/index.ts';
import type { SchemaWithPipeAsync } from '../../methods/index.ts';
import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts';
import {
string,
Expand Down Expand Up @@ -80,6 +82,12 @@ describe('undefinedableAsync', () => {
StringSchema<undefined>,
() => Promise<'foo'>
>;
type Schema7 = UndefinedableSchemaAsync<
SchemaWithPipeAsync<
[StringSchema<undefined>, TransformActionAsync<string, number>]
>,
'foo'
>;

test('of input', () => {
type Input = string | undefined;
Expand All @@ -89,6 +97,7 @@ describe('undefinedableAsync', () => {
expectTypeOf<InferInput<Schema4>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema5>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema6>>().toEqualTypeOf<Input>();
expectTypeOf<InferInput<Schema7>>().toEqualTypeOf<Input>();
});

test('of output', () => {
Expand All @@ -98,6 +107,7 @@ describe('undefinedableAsync', () => {
expectTypeOf<InferOutput<Schema4>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema5>>().toEqualTypeOf<string | undefined>();
expectTypeOf<InferOutput<Schema6>>().toEqualTypeOf<string>();
expectTypeOf<InferOutput<Schema7>>().toEqualTypeOf<number>();
});

test('of issue', () => {
Expand All @@ -107,6 +117,7 @@ describe('undefinedableAsync', () => {
expectTypeOf<InferIssue<Schema4>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema5>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema6>>().toEqualTypeOf<StringIssue>();
expectTypeOf<InferIssue<Schema7>>().toEqualTypeOf<StringIssue>();
});
});
});

0 comments on commit 532fbcb

Please sign in to comment.