diff --git a/library/CHANGELOG.md b/library/CHANGELOG.md index 92f1ce498..3c6164303 100644 --- a/library/CHANGELOG.md +++ b/library/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the library will be documented in this file. - Add `nanoid` action to validate Nano IDs (pull request #789) - Add `undefinedable` and `undefinedableAsync` schema (issue #385) +- Fix invalid output type for transformed optional object entries (issue #806) ## v0.39.0 (August 24, 2024) diff --git a/library/src/schemas/looseObject/looseObject.test-d.ts b/library/src/schemas/looseObject/looseObject.test-d.ts index 05284b2eb..adc1f72f6 100644 --- a/library/src/schemas/looseObject/looseObject.test-d.ts +++ b/library/src/schemas/looseObject/looseObject.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; @@ -48,6 +48,12 @@ describe('looseObject', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, undefined >; @@ -61,6 +67,7 @@ describe('looseObject', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; } & { [key: string]: unknown } >(); }); @@ -74,6 +81,7 @@ describe('looseObject', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; } & { [key: string]: unknown } >(); }); diff --git a/library/src/schemas/looseObject/looseObjectAsync.test-d.ts b/library/src/schemas/looseObject/looseObjectAsync.test-d.ts index 44b56bfa6..f16257b8e 100644 --- a/library/src/schemas/looseObject/looseObjectAsync.test-d.ts +++ b/library/src/schemas/looseObject/looseObjectAsync.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; @@ -53,6 +53,12 @@ describe('looseObjectAsync', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, undefined >; @@ -66,6 +72,7 @@ describe('looseObjectAsync', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; } & { [key: string]: unknown } >(); }); @@ -79,6 +86,7 @@ describe('looseObjectAsync', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; } & { [key: string]: unknown } >(); }); diff --git a/library/src/schemas/object/object.test-d.ts b/library/src/schemas/object/object.test-d.ts index 51e13c917..7592be303 100644 --- a/library/src/schemas/object/object.test-d.ts +++ b/library/src/schemas/object/object.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; @@ -47,6 +47,12 @@ describe('object', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, undefined >; @@ -59,6 +65,7 @@ describe('object', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; }>(); }); @@ -70,6 +77,7 @@ describe('object', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; }>(); }); diff --git a/library/src/schemas/object/objectAsync.test-d.ts b/library/src/schemas/object/objectAsync.test-d.ts index ea891e200..8439246d3 100644 --- a/library/src/schemas/object/objectAsync.test-d.ts +++ b/library/src/schemas/object/objectAsync.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; @@ -47,6 +47,12 @@ describe('objectAsync', () => { key4: ObjectSchemaAsync<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, undefined >; @@ -59,6 +65,7 @@ describe('objectAsync', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; }>(); }); @@ -70,6 +77,7 @@ describe('objectAsync', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; }>(); }); diff --git a/library/src/schemas/objectWithRest/objectWithRest.test-d.ts b/library/src/schemas/objectWithRest/objectWithRest.test-d.ts index 6464c4ee8..17dbbfbf0 100644 --- a/library/src/schemas/objectWithRest/objectWithRest.test-d.ts +++ b/library/src/schemas/objectWithRest/objectWithRest.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { BooleanIssue, BooleanSchema } from '../boolean/index.ts'; @@ -57,6 +57,12 @@ describe('objectWithRest', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, BooleanSchema, undefined @@ -71,6 +77,7 @@ describe('objectWithRest', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; } & { [key: string]: boolean } >(); }); @@ -84,6 +91,7 @@ describe('objectWithRest', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; } & { [key: string]: boolean } >(); }); diff --git a/library/src/schemas/objectWithRest/objectWithRestAsync.test-d.ts b/library/src/schemas/objectWithRest/objectWithRestAsync.test-d.ts index fd75024a5..bb5d11195 100644 --- a/library/src/schemas/objectWithRest/objectWithRestAsync.test-d.ts +++ b/library/src/schemas/objectWithRest/objectWithRestAsync.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { BooleanIssue, BooleanSchema } from '../boolean/index.ts'; @@ -60,6 +60,12 @@ describe('objectWithRestAsync', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, BooleanSchema, undefined @@ -74,6 +80,7 @@ describe('objectWithRestAsync', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; } & { [key: string]: boolean } >(); }); @@ -87,6 +94,7 @@ describe('objectWithRestAsync', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; } & { [key: string]: boolean } >(); }); diff --git a/library/src/schemas/strictObject/strictObject.test-d.ts b/library/src/schemas/strictObject/strictObject.test-d.ts index 174b2abfb..b8cbe80e7 100644 --- a/library/src/schemas/strictObject/strictObject.test-d.ts +++ b/library/src/schemas/strictObject/strictObject.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; @@ -48,6 +48,12 @@ describe('strictObject', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, undefined >; @@ -60,6 +66,7 @@ describe('strictObject', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; }>(); }); @@ -71,6 +78,7 @@ describe('strictObject', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; }>(); }); diff --git a/library/src/schemas/strictObject/strictObjectAsync.test-d.ts b/library/src/schemas/strictObject/strictObjectAsync.test-d.ts index 6a5ed5c8d..73e0b62a1 100644 --- a/library/src/schemas/strictObject/strictObjectAsync.test-d.ts +++ b/library/src/schemas/strictObject/strictObjectAsync.test-d.ts @@ -1,5 +1,5 @@ import { describe, expectTypeOf, test } from 'vitest'; -import type { ReadonlyAction } from '../../actions/index.ts'; +import type { ReadonlyAction, TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; @@ -53,6 +53,12 @@ describe('strictObjectAsync', () => { key4: ObjectSchema<{ key: NumberSchema }, never>; key5: SchemaWithPipe<[StringSchema, ReadonlyAction]>; key6: UndefinedableSchema, 'bar'>; + key7: SchemaWithPipe< + [ + OptionalSchema, never>, + TransformAction, + ] + >; }, undefined >; @@ -65,6 +71,7 @@ describe('strictObjectAsync', () => { key4: { key: number }; key5: string; key6: string | undefined; + key7?: string; }>(); }); @@ -76,6 +83,7 @@ describe('strictObjectAsync', () => { key4: { key: number }; readonly key5: string; key6: string; + key7: string; }>(); }); diff --git a/library/src/types/object.ts b/library/src/types/object.ts index 17c66d123..de726fe0e 100644 --- a/library/src/types/object.ts +++ b/library/src/types/object.ts @@ -165,9 +165,11 @@ type OptionalInputKeys = { */ type OptionalOutputKeys = { [TKey in keyof TEntries]: TEntries[TKey] extends QuestionMarkSchema - ? HasDefault extends true - ? never - : TKey + ? undefined extends InferOutput + ? HasDefault extends false + ? TKey + : never + : never : never; }[keyof TEntries];