@contember/typesafe
Advanced tools
Comparing version 1.2.0-beta.1 to 1.2.0-beta.2
@@ -41,3 +41,6 @@ declare type Unpacked<T> = T extends readonly (infer U)[] ? U : never; | ||
export declare const union: <T extends Type<Json>[]>(...inner: T) => Type<ReturnType<Unpacked<T>>>; | ||
export declare const discriminatedUnion: <T extends Type<JsonObject>[]>(field: string, ...inner: T) => Type<ReturnType<Unpacked<T>>>; | ||
export declare const partiallyDiscriminatedUnion: <T extends Type<JsonObject>[]>(field: string, ...inner: T) => Type<ReturnType<Unpacked<T>>>; | ||
export declare const discriminatedUnion: <F extends string, T extends { | ||
[key: string]: JsonObject; | ||
}>(field: F, inner: { [K in keyof T]: Type<T[K]>; }) => Type<{ [K_1 in keyof T]: { [X in F]: K_1; } & T[K_1]; }[keyof T]>; | ||
declare type TupleFromTupledType<T extends Type<Json>[]> = T extends [Type<infer X>, ...infer Y] ? (Y extends Type<Json>[] ? readonly [X, ...TupleFromTupledType<Y>] : readonly []) : readonly []; | ||
@@ -44,0 +47,0 @@ export declare const tuple: <T extends Type<Json>[]>(...inner: T) => Type<TupleFromTupledType<T>>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.valueAt = exports.coalesce = exports.transform = exports.nullable = exports.false_ = exports.true_ = exports.null_ = exports.enumeration = exports.intersection = exports.discriminatedTupleUnion = exports.tuple = exports.discriminatedUnion = exports.union = exports.record = exports.noExtraProps = exports.partial = exports.object = exports.array = exports.literal = exports.anyJsonObject = exports.anyJson = exports.scalar = exports.boolean = exports.integer = exports.number = exports.string = exports.fail = exports.ParseError = void 0; | ||
exports.valueAt = exports.coalesce = exports.transform = exports.nullable = exports.false_ = exports.true_ = exports.null_ = exports.enumeration = exports.intersection = exports.discriminatedTupleUnion = exports.tuple = exports.discriminatedUnion = exports.partiallyDiscriminatedUnion = exports.union = exports.record = exports.noExtraProps = exports.partial = exports.object = exports.array = exports.literal = exports.anyJsonObject = exports.anyJson = exports.scalar = exports.boolean = exports.integer = exports.number = exports.string = exports.fail = exports.ParseError = void 0; | ||
const node_util_1 = require("node:util"); | ||
@@ -212,3 +212,3 @@ class ParseError extends Error { | ||
exports.union = union; | ||
const discriminatedUnion = (field, ...inner) => { | ||
const partiallyDiscriminatedUnion = (field, ...inner) => { | ||
const type = (input, path = []) => { | ||
@@ -237,2 +237,19 @@ const errors = []; | ||
}; | ||
exports.partiallyDiscriminatedUnion = partiallyDiscriminatedUnion; | ||
const discriminatedUnion = (field, inner) => { | ||
const type = (input, path = []) => { | ||
if (input === null || typeof input !== 'object') | ||
throw ParseError.format(input, path, 'object'); | ||
const key = input[field]; | ||
if (typeof key !== 'string') | ||
throw ParseError.format(key, [...path, field], 'string'); | ||
const discriminatedType = inner[key]; | ||
if (discriminatedType === undefined) | ||
throw ParseError.format(key, [...path, field], Object.keys(inner).join('|')); | ||
const { [field]: _, ...inputWithoutDiscr } = input; | ||
return { [field]: key, ...discriminatedType(inputWithoutDiscr) }; | ||
}; | ||
type.inner = inner; | ||
return type; | ||
}; | ||
exports.discriminatedUnion = discriminatedUnion; | ||
@@ -239,0 +256,0 @@ const tuple = (...inner) => { |
{ | ||
"name": "@contember/typesafe", | ||
"version": "1.2.0-beta.1", | ||
"version": "1.2.0-beta.2", | ||
"license": "Apache-2.0", | ||
@@ -5,0 +5,0 @@ "main": "dist/src/index.js", |
@@ -245,3 +245,3 @@ import { isDeepStrictEqual } from 'node:util' | ||
export const discriminatedUnion = <T extends Type<JsonObject>[]>(field: string, ...inner: T): Type<ReturnType<Unpacked<T>>> => { | ||
export const partiallyDiscriminatedUnion = <T extends Type<JsonObject>[]>(field: string, ...inner: T): Type<ReturnType<Unpacked<T>>> => { | ||
const type = (input: unknown, path: PropertyKey[] = []): ReturnType<Unpacked<T>> => { | ||
@@ -271,2 +271,21 @@ const errors = [] | ||
export const discriminatedUnion = <F extends string, T extends {[key: string]: JsonObject}>(field: F, inner: {[K in keyof T]: Type<T[K]>}): Type<{ [K in keyof T]: { [X in F]: K } & T[K] }[keyof T]> => { | ||
const type = (input: unknown, path: PropertyKey[] = []): { [K in keyof T]: { [X in F]: K } & T[K] }[keyof T] => { | ||
if (input === null || typeof input !== 'object') throw ParseError.format(input, path, 'object') | ||
const key = (input as any)[field] | ||
if (typeof key !== 'string') throw ParseError.format(key, [...path, field], 'string') | ||
const discriminatedType = inner[key] | ||
if (discriminatedType === undefined) throw ParseError.format(key, [...path, field], Object.keys(inner).join('|')) | ||
const { [field]: _, ...inputWithoutDiscr } = input | ||
return { [field]: key, ...discriminatedType(inputWithoutDiscr) } | ||
} | ||
type.inner = inner | ||
return type | ||
} | ||
type TupleFromTupledType<T extends Type<Json>[]> = T extends [Type<infer X>, ...infer Y] | ||
@@ -273,0 +292,0 @@ ? (Y extends Type<Json>[] ? readonly [X, ...TupleFromTupledType<Y>] : readonly []) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
76204
771