Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions src/mergeProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@ import { isJSONSchemaObjectType } from './utils';
/**
* Merge and dedupe 2 tuples
*/
type MergeTuples<T1, T2> = readonly [
...UnionToTuple<TupleToUnion<T1> | TupleToUnion<T2>>,
];
type MergeTuples<T1, T2> = Readonly<
UnionToTuple<TupleToUnion<T1> | TupleToUnion<T2>>
>;

/**
* Merge two optional records, keeping `undefined` if both are undefined
*/
type MergeOptionalRecords<
Object1 extends Record<string, unknown> | undefined,
Object2 extends Record<string, unknown> | undefined,
A extends Record<string, unknown> | undefined,
B extends Record<string, unknown> | undefined,
> =
Object1 extends Record<string, unknown>
? Object2 extends Record<string, unknown>
? Merge<Object1, Object2>
: Object1
: Object2 extends Record<string, unknown>
? Object2
A extends Record<string, unknown>
? B extends Record<string, unknown>
? Merge<A, B>
: A
: B extends Record<string, unknown>
? B
: undefined;

type MergeProps<
Expand Down
18 changes: 7 additions & 11 deletions src/omitProps.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import type { Merge, SetRequired, TupleToUnion, UnionToTuple } from 'type-fest';
import type { Merge, SetRequired } from 'type-fest';

import type { JSONSchemaObject, JSONSchemaObjectOutput } from './types';
import type {
JSONSchemaObject,
JSONSchemaObjectOutput,
OmitFromTuple,
} from './types';
import { isJSONSchemaObjectType } from './utils';

type OmitFromTuple<Tuple extends readonly unknown[], EntriesToOmit> = Readonly<
UnionToTuple<Exclude<TupleToUnion<Tuple>, EntriesToOmit>>
>;

type OmitSchemaProperties<
Schema extends JSONSchemaObject,
Keys extends (keyof Schema['properties'])[],
Expand All @@ -16,11 +16,7 @@ type OmitSchemaProperties<
properties: Omit<Schema['properties'], Keys[number]>;
required: undefined extends Schema['required']
? undefined
: OmitFromTuple<
// @ts-expect-error extends doesn't narrow type
Schema['required'],
Keys[number]
>;
: OmitFromTuple<Schema['required'], Keys[number]>;
}
>;

Expand Down
14 changes: 7 additions & 7 deletions src/optionalProps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { Merge, TupleToUnion, UnionToTuple } from 'type-fest';
import type { Merge } from 'type-fest';

import type { JSONSchemaObject, JSONSchemaObjectOutput } from './types';
import type {
JSONSchemaObject,
JSONSchemaObjectOutput,
OmitFromTuple,
} from './types';
import { isJSONSchemaObjectType } from './utils';

type ObjectKeys = string | number | symbol;
Expand All @@ -15,11 +19,7 @@ type OptionalProps<
Merge<
Schema,
{
required: Readonly<
UnionToTuple<
Exclude<TupleToUnion<Schema['required']>, TupleToUnion<Keys>>
>
>;
required: OmitFromTuple<Schema['required'], NonNullable<Keys>[number]>;
}
>;
/**
Expand Down
32 changes: 17 additions & 15 deletions src/sealSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@ import type { Merge } from 'type-fest';
import type { JSONSchema, JSONSchemaObjectOutput } from './types';
import { isObject } from './utils';

type DisableAdditionalProperties<Value extends object> =
'type' extends keyof Value
? Value['type'] extends 'object'
? Merge<Value, Readonly<{ additionalProperties: false }>>
: Value
: Value;

type DisableAdditionalPropertiesDeep<
_Value extends object,
Value = DisableAdditionalProperties<_Value>,
> = {
[Key in keyof Value]: Value[Key] extends object
? DisableAdditionalPropertiesDeep<Value[Key]>
: Value[Key];
};
type DisableAdditionalPropertiesDeep<Value> = Value extends object
? Value extends { type: 'object' }
? // JSON schema object type
Readonly<
Merge<
{
[Key in keyof Value]: DisableAdditionalPropertiesDeep<Value[Key]>;
},
{ additionalProperties: false }
>
>
: // Any other object/array
Readonly<{
[Key in keyof Value]: DisableAdditionalPropertiesDeep<Value[Key]>;
}>
: // Any other primitive
Value;

function disableAdditionalPropertiesDeep(item: unknown): unknown {
if (isObject(item)) {
Expand Down
7 changes: 7 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type {
OverrideProperties,
SetRequired,
Simplify,
TupleToUnion,
UnionToTuple,
} from 'type-fest';

// https://github.com/ThomasAribart/json-schema-to-ts/blob/12767c1eab895159c01f5e6898d8e5e711ff9d1c/src/definitions/jsonSchema.ts
Expand All @@ -27,3 +29,8 @@ export type JSONSchemaObjectOutput<Schema> = Simplify<
ConditionalExcept<Schema, readonly [] | undefined>
>
>;

export type OmitFromTuple<
Tuple extends readonly unknown[] | undefined,
EntriesToOmit,
> = Readonly<UnionToTuple<Exclude<TupleToUnion<Tuple>, EntriesToOmit>>>;
29 changes: 15 additions & 14 deletions src/unsealSchema.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import type { JSONSchema, JSONSchemaObjectOutput } from './types';
import { isObject } from './utils';

type OmitAdditionalProperty<Value extends object> = 'type' extends keyof Value
? Value['type'] extends 'object'
? Omit<Value, 'additionalProperties'>
: Value
: Value;

type OmitAdditionalPropertiesDeep<
_Value extends object,
Value = OmitAdditionalProperty<_Value>,
> = {
[Key in keyof Value]: Value[Key] extends object
? OmitAdditionalPropertiesDeep<Value[Key]>
: Value[Key];
};
type OmitAdditionalPropertiesDeep<Value> = Value extends object
? Value extends { type: 'object' }
? // JSON schema object type
Readonly<{
[Key in keyof Omit<
Value,
'additionalProperties'
>]: OmitAdditionalPropertiesDeep<Value[Key]>;
}>
: // Any other object/array
Readonly<{
[Key in keyof Value]: OmitAdditionalPropertiesDeep<Value[Key]>;
}>
: // Any other primitive
Value;

function omitAdditionalPropertiesDeep(item: unknown): unknown {
if (isObject(item)) {
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"isolatedModules": true,
"erasableSyntaxOnly": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true
"noImplicitOverride": true,
"noErrorTruncation": true
},
"exclude": ["./dist"]
}
Loading