mirror of
https://github.com/zoriya/typebox.git
synced 2026-05-22 23:05:02 +00:00
Revision 0.31.14 (#584)
* Revert 0.31.8 Enum * Intercept for Enum on StaticDecode
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@sinclair/typebox",
|
||||
"version": "0.31.13",
|
||||
"version": "0.31.14",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@sinclair/typebox",
|
||||
"version": "0.31.13",
|
||||
"version": "0.31.14",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@sinclair/hammer": "^0.17.1",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sinclair/typebox",
|
||||
"version": "0.31.13",
|
||||
"version": "0.31.14",
|
||||
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
|
||||
"keywords": [
|
||||
"typescript",
|
||||
|
||||
+9
-7
@@ -176,6 +176,7 @@ export type TAnySchema =
|
||||
| TBoolean
|
||||
| TConstructor
|
||||
| TDate
|
||||
| TEnum
|
||||
| TFunction
|
||||
| TInteger
|
||||
| TIntersect
|
||||
@@ -340,11 +341,12 @@ export interface TDate extends TSchema, DateOptions {
|
||||
export type TEnumRecord = Record<TEnumKey, TEnumValue>
|
||||
export type TEnumValue = string | number
|
||||
export type TEnumKey = string
|
||||
export type TEnumToLiteralUnion<T extends TEnumValue> = T extends TEnumValue ? (string extends T ? TNever : TLiteral<T>) : never
|
||||
// ^ empty enums evaluate as string
|
||||
export type TEnumToLiteralTuple<T extends TEnumValue> = UnionToTuple<TEnumToLiteralUnion<T>>
|
||||
export type TEnumToUnion<T extends TEnumValue> = UnionType<AssertRest<TEnumToLiteralTuple<T>>>
|
||||
export type TEnum<T extends TEnumRecord> = TEnumToUnion<T[keyof T]>
|
||||
export interface TEnum<T extends Record<string, string | number> = Record<string, string | number>> extends TSchema {
|
||||
[Kind]: 'Union'
|
||||
[Hint]: 'Enum'
|
||||
static: T[keyof T]
|
||||
anyOf: TLiteral<T[keyof T]>[]
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// TExtends
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -868,6 +870,7 @@ export type DecodeType<T extends TSchema> = (
|
||||
T extends TArray<infer S extends TSchema> ? TArray<DecodeType<S>> :
|
||||
T extends TAsyncIterator<infer S extends TSchema> ? TAsyncIterator<DecodeType<S>> :
|
||||
T extends TConstructor<infer P extends TSchema[], infer R extends TSchema> ? TConstructor<P, DecodeType<R>> :
|
||||
T extends TEnum<infer S> ? TEnum<S> : // intercept for union. interior non decodable
|
||||
T extends TFunction<infer P extends TSchema[], infer R extends TSchema> ? TFunction<P, DecodeType<R>> :
|
||||
T extends TIntersect<infer S extends TSchema[]> ? TIntersect<DecodeRest<S>> :
|
||||
T extends TIterator<infer S extends TSchema> ? TIterator<DecodeType<S>> :
|
||||
@@ -2899,12 +2902,11 @@ export class JsonTypeBuilder extends TypeBuilder {
|
||||
}
|
||||
/** `[Json]` Creates a Enum type */
|
||||
public Enum<V extends TEnumValue, T extends Record<TEnumKey, V>>(item: T, options: SchemaOptions = {}): TEnum<T> {
|
||||
if (ValueGuard.IsUndefined(item)) return this.Never(options) as TEnum<T>
|
||||
// prettier-ignore
|
||||
const values1 = Object.getOwnPropertyNames(item).filter((key) => isNaN(key as any)).map((key) => item[key]) as T[keyof T][]
|
||||
const values2 = [...new Set(values1)]
|
||||
const anyOf = values2.map((value) => Type.Literal(value))
|
||||
return this.Union(anyOf, options) as TEnum<T>
|
||||
return this.Union(anyOf, { ...options, [Hint]: 'Enum' }) as TEnum<T>
|
||||
}
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
public Extends<L extends TSchema, R extends TSchema, T extends TSchema, U extends TSchema>(left: L, right: R, trueType: T, falseType: U, options: SchemaOptions = {}): TExtends<L, R, T, U> {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Assert } from '../../assert'
|
||||
import { Value } from '@sinclair/typebox/value'
|
||||
import { Type } from '@sinclair/typebox'
|
||||
|
||||
describe('value/transform/Enum', () => {
|
||||
enum E {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
// --------------------------------------------------------
|
||||
// Identity
|
||||
// --------------------------------------------------------
|
||||
const T0 = Type.Transform(Type.Enum(E))
|
||||
.Decode((value) => value)
|
||||
.Encode((value) => value)
|
||||
it('Should decode identity', () => {
|
||||
const R = Value.Decode(T0, E.A)
|
||||
Assert.IsEqual(R, E.A)
|
||||
})
|
||||
it('Should encode identity', () => {
|
||||
const R = Value.Encode(T0, E.A)
|
||||
Assert.IsEqual(R, E.A)
|
||||
})
|
||||
it('Should throw on identity decode', () => {
|
||||
Assert.Throws(() => Value.Decode(T0, null))
|
||||
})
|
||||
// --------------------------------------------------------
|
||||
// Mapped
|
||||
// --------------------------------------------------------
|
||||
const T1 = Type.Transform(Type.Enum(E))
|
||||
.Decode((value) => 1)
|
||||
.Encode((value) => E.A)
|
||||
it('Should decode mapped', () => {
|
||||
const R = Value.Decode(T1, E.A)
|
||||
Assert.IsEqual(R, 1)
|
||||
})
|
||||
it('Should encode mapped', () => {
|
||||
const R = Value.Encode(T1, null)
|
||||
Assert.IsEqual(R, E.A)
|
||||
})
|
||||
it('Should throw on mapped decode', () => {
|
||||
Assert.Throws(() => Value.Decode(T1, null))
|
||||
})
|
||||
})
|
||||
@@ -6,6 +6,7 @@ import './bigint'
|
||||
import './boolean'
|
||||
import './constructor'
|
||||
import './date'
|
||||
import './enum'
|
||||
import './function'
|
||||
import './integer'
|
||||
import './intersect'
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import { Type } from '@sinclair/typebox'
|
||||
// expect empty enum to be string (as empty enums T[keyof T] evaluates as string)
|
||||
enum E {}
|
||||
const T = Type.Enum(E)
|
||||
Expect(T).ToStaticNever()
|
||||
Expect(T).ToStatic<string>()
|
||||
}
|
||||
{
|
||||
// expect empty enum to be never
|
||||
|
||||
@@ -78,9 +78,5 @@ import { Type, Static } from '@sinclair/typebox'
|
||||
C = 'Z',
|
||||
}
|
||||
const T = Type.Record(Type.Enum(E), Type.Number())
|
||||
Expect(T).ToStatic<{
|
||||
X: number
|
||||
Y: number
|
||||
Z: number
|
||||
}>()
|
||||
Expect(T).ToStatic<{}>()
|
||||
}
|
||||
|
||||
@@ -278,3 +278,16 @@ import { Expect } from './assert'
|
||||
Expect(T).ToStaticDecode<number>()
|
||||
Expect(GenericIntersect(T)).ToStaticDecode<1>()
|
||||
}
|
||||
{
|
||||
// should decode enum
|
||||
enum E {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
const T = Type.Transform(Type.Enum(E))
|
||||
.Decode((value) => 1 as const)
|
||||
.Encode((value) => E.A)
|
||||
Expect(T).ToStaticDecode<1>()
|
||||
Expect(T).ToStaticEncode<E>()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user