Skip to content

Commit

Permalink
add override utility
Browse files Browse the repository at this point in the history
  • Loading branch information
ytw0728 committed Mar 10, 2023
1 parent 03d65bd commit 18b447b
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/structs/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { Struct, Context, Validator } from '../struct'
import { object, optional, type } from './types'
import { ObjectSchema, Assign, ObjectType, PartialObjectSchema } from '../utils'
import {
ObjectSchema,
Assign,
ObjectType,
PartialObjectSchema,
OverrideSourceType,
} from '../utils'

/**
* Create a new struct that combines the properties properties from multiple
Expand Down Expand Up @@ -59,6 +65,20 @@ export function assign(...Structs: Struct<any>[]): any {
return isType ? type(schema) : object(schema)
}

/**
* Create a new struct based on target struct and overridden by source struct.
*/

export function override<
A extends ObjectSchema,
B extends OverrideSourceType<A>
>(
target: Struct<ObjectType<A>, A>,
source: B
): Struct<ObjectType<Assign<A, B>>, Assign<A, B>> {
return assign(target, type(source))
}

/**
* Define a new struct type with a custom validation function.
*/
Expand Down
9 changes: 9 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,15 @@ export type ObjectType<S extends ObjectSchema> = Simplify<
Optionalize<{ [K in keyof S]: Infer<S[K]> }>
>

/**
* A schema for source type of override utility.
*/

export type OverrideSourceType<T extends ObjectSchema> = Partial<
Record<keyof T, AnyStruct>
> &
ObjectSchema

/**
* Omit properties from a type that extend from a specific type.
*/
Expand Down
28 changes: 28 additions & 0 deletions test/validation/override/invalid-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { object, override, string, number } from '../../../src'

const Target = object({ a: string() })

export const Struct = override(Target, { a: number(), b: number() })

export const data = {
a: 'invalid',
b: 2,
c: 5,
}

export const failures = [
{
value: 'invalid',
type: 'number',
refinement: undefined,
path: ['a'],
branch: [data, data.a],
},
{
branch: [data, data.c],
path: ['c'],
refinement: undefined,
type: 'never',
value: 5,
},
]
21 changes: 21 additions & 0 deletions test/validation/override/invalid-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { type, override, string, number } from '../../../src'

const Target = type({ a: string() })

export const Struct = override(Target, { a: number(), b: number() })

export const data = {
a: 'invalid',
b: 2,
c: 5,
}

export const failures = [
{
value: 'invalid',
type: 'number',
refinement: undefined,
path: ['a'],
branch: [data, data.a],
},
]
15 changes: 15 additions & 0 deletions test/validation/override/valid-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { type, override, string, number } from '../../../src'

const Target = type({ a: string() })

export const Struct = override(Target, { a: number(), b: number() })

export const data = {
a: 1,
b: 2,
}

export const output = {
a: 1,
b: 2,
}
17 changes: 17 additions & 0 deletions test/validation/override/valid-type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { type, override, string, number } from '../../../src'

const Target = type({ a: string() })

export const Struct = override(Target, { b: number() })

export const data = {
a: '1',
b: 2,
c: 3,
}

export const output = {
a: '1',
b: 2,
c: 3,
}

0 comments on commit 18b447b

Please sign in to comment.