Closed dswbx closed 1 month ago
@dswbx Hi,
By default, the TypeBox compiler and value checkers will only validate against structures defined by TypeBox (so it only checks a subset of the specification). This may change in later revisions where there is some consideration going towards developing a full standards compliant validator that supports all keywords, but this is a fair way off.
In the interim, you can register custom schematics + inference in the following way.
import { Type, Kind, SchemaOptions, TypeRegistry, Static } from '@sinclair/typebox'
import { Value } from 'src/value/value'
// create a custom type on the type registry
TypeRegistry.Set('StringEnum', (schema: { enum: string[] }, value: unknown) => {
return typeof value === 'string' && schema.enum.includes(value)
})
// create a type method for string enum
export function StringEnum<T extends string[]>(values: [...T], options: SchemaOptions = {}) {
return Type.Unsafe<T[number]>({ ...options, [Kind]: 'StringEnum', enum: values })
}
// use as custom type
const T = StringEnum(['A', 'B', 'C']) // TUnsafe<'A' | 'B' | 'C'>
type T = Static<typeof T> // 'A' | 'B' | 'C'
Value.Check(T, 'A') // true
Value.Check(T, 'B') // true
Value.Check(T, 'C') // true
Value.Check(T, 'D') // false
By setting a custom validator on the TypeRegistry, this will allow you use Value.Check
and TypeCompiler
to check enum values.
Hope this helps
S
@sinclairzx81 thank you very much, this works nicely! Any chance to modify the error message (so that I can specify that the kind is matched but the value is wrong)? (EDIT: found it and updated my example. Works great!)
I understand that you might have a different focus, since there are many validators around. But would you accept a pull request to add the enum-check on string types? As far as I can say that's a very common use-case, e.g. and the pattern
is supported. I could probably add this inside this function (along with a unit test of course).
as a way to overcome it you can do Value.Decode catching the error and narrowing the error type with Value.Errors
try {
const r = Value.Decode(User, u);
return { _tag: 'right', value: r };
} catch (e) {
// type of their errors is unknown, you should additionally call error list methods
return { _tag: 'left', error: [...Value.Errors(User, u)] };
}
@dswbx Hi, Apologies for the delay in reply.
I understand that you might have a different focus, since there are many validators around. But would you accept a pull request to add the enum-check on string types? As far as I can say that's a very common use-case, e.g. and the pattern is supported. I could probably add this inside this function (along with a unit test of course).
Unfortunately, I can't accept any updates to the current Enum schematics at this time (mostly to lock down this aspect of the library so I've a basis for updating it). The eventual goal is to reshape Type.Enum
into a { enum: [...] }
, which requires fairly heavy refactoring of how TB currently handles Union types. The current setup is fairly consistent around anyOf
(schematics, inference and validation) so just want to keep things as they are so I can investigate reshaping things from a consistent state (there is a lot of complexity down there)
Thanks for the offer tho, but can only really advise the using the approach shown above for now. Will close off this issue for now. All the best! S
If I use
Type.String({ enum: [...] })
theCheck
function only checks if the value given is a string. Here is an example comparing it toajv
and@cfworker/json-schema
:I've read in other issues, that I could use a
Union
withLiteral
's, but this would mess up my schema (and want to keep it readable). Is there a reason why enums forString
aren't checked (like limitation, or just no completed yet)? Alternatively, are there ways I could still useCheck
, like can I add custom validations?(I can't use AJV because I'm using it inside a cloudflare worker, and while
@cfworker/json-schema
works good, I'd still prefer to use a single library).Thanks in advance!