Creating Schema Combinators for Complex Transformations in TypeScript

I have found myself in need for a couple of schema combinators that simplify handling complex schema transformations in a declarative way. What do you think about my approach? Are there downsides? (ignore the custom dual definition)

composeExtend
export declare namespace composeExtend {
    export type DataFirst = <A1, I1, R1, A2, I2, R2>(
        fromSchema: Schema.Schema<A1, I1, R1>,
        extension: Schema.Schema<A2, I2, R2>
    ) => Schema.transform<
        Schema.Schema<A1, I1, R1>,
        Schema.extend<Schema.Schema<A1, I1, R1>, Schema.Schema<A2, I2, R2>>
    >
    export type DataLast = <A2, I2, R2>(
        extension: Schema.Schema<A2, I2, R2>
    ) => <A1, I1, R1>(
        fromSchema: Schema.Schema<A1, I1, R1>
    ) => Schema.transform<
        Schema.Schema<A1, I1, R1>,
        Schema.extend<Schema.Schema<A1, I1, R1>, Schema.Schema<A2, I2, R2>>
    >
    export type Signature = DataLast & DataFirst
}
export const composeExtend: composeExtend.Signature = dual<composeExtend.DataFirst, composeExtend.Signature>(
    2,
    (fromSchema, extension) => Schema.compose(fromSchema, Schema.extend(fromSchema, extension), { strict: false })
)


exclude
export declare namespace exclude {
    export type DataFirst = <A1, I1, R1, A2, I2, R2>(
        exclude: Schema.Schema<A1, I1, R1>,
        fromSchema: Schema.Schema<A2, Exclude<I2, A1>, R2>
    ) => Schema.transform<
        Schema.Union<[Schema.Schema<A1, I1, R1>, Schema.Schema<A2, Exclude<I2, A1>, R2>]>,
        Schema.Schema<A2, Exclude<I2, A1>, R2>
    >
    export type DataLast = <A1, I1, R1>(
        exclude: Schema.Schema<A1, I1, R1>
    ) => <A2, I2, R2>(
        fromSchema: Schema.Schema<A2, Exclude<I2, A1>, R2>
    ) => Schema.transform<
        Schema.Union<[Schema.Schema<A1, I1, R1>, Schema.Schema<A2, Exclude<I2, A1>, R2>]>,
        Schema.Schema<A2, Exclude<I2, A1>, R2>
    >
    export type Signature = DataLast & DataFirst
}
Was this page helpful?