Value dependant types #270
-
Hey! Just found this gem of a repo, and thought I'd give a whirl. It's working incredibly well and could potentially save a lot of work! Nice job 🎉 I've run into a headscratcher as I can't seem to find out how to solve the following TS types with Typebox. I've built a query builder of sort which means the JSON object I can pass through have different variations. As an example: // The type of value changes dependant on the operator value
const body = {
set: 'dog',
filters: [
{
field: 'breed',
operator: 'in',
value: ['Beagle', 'Labrador']
},
{
field: 'weight',
operator: 'range',
value: {
from: 0,
to: 100
}
},
]
}; Another variation of the same issue could be this, which can be cumbersomely handled by splitting the validation. import Ajv from 'ajv'
import { Static, Type } from "@sinclair/typebox";
const ajv = new Ajv();
function StringEnum<T extends string[]>(values: [...T]) {
return Type.Unsafe<T[number]>({ type: 'string', enum: values })
}
const ImportSchema = Type.Object({
importIds: Type.Array(Type.Integer())
})
const UserSchema = Type.Object({
userIds: Type.Array(Type.Integer())
})
const DefinitionSchemas = {
import: ImportSchema,
user: UserSchema,
}
const ConfigSchema = Type.Object({
campaignId: Type.Number(),
type: StringEnum(['import', 'user']),
definition: Type.Unknown()
})
const segment: Static<typeof ConfigSchema> = {
"type": "user",
"campaignId": 1,
"definition": {
"userIds": [1, 2, 3]
}
}
if (
ajv.validate(ConfigSchema, segment)
&& ajv.validate(DefinitionSchemas[segment.type], segment.definition)
) {
console.log('Hooraaay!')
}
console.log(ajv.errors) So my question really is, how do I create a type that changes dependant on a value of a sibling with validation for the TypeCompiler or ajv? Hope to hear from anyone smarter than me! 🤞🏼 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
I've also tried something like this, which don't work: const ImportSchema = Type.Object({
type: Type.Literal('import'),
definition: Type.Object({
importIds: Type.Array(Type.Integer())
})
})
const UserSchema = Type.Object({
type: Type.Literal('import'),
definition: Type.Object({
userIds: Type.Array(Type.Integer())
})
})
export const ConfigSchema = Type.Intersect([
Type.Object({
campaignId: Type.Number(),
}),
Type.Union([ImportSchema, UserSchema])
]) |
Beta Was this translation helpful? Give feedback.
I've also tried something like this, which don't work: