A
arktypeβ€’3w ago
L0xus

Narrow type based on another property's value

Hey, I've been using ArkType for a few days now - loving it so far. One thing I'd love to be able to do is narrow a type based on the value of another property in the object. eg.
const myType = type("'string' | 'Color'")

const myValue = type({
type: myType,
value: type("'string' | 'string.hex'")
})
const myType = type("'string' | 'Color'")

const myValue = type({
type: myType,
value: type("'string' | 'string.hex'")
})
given this code, I would want the type of 'value' to change based on the 'type' property. if 'type ' is 'string', then I'd want value to be narrowed to 'string', but if 'type' is 'Color', I'd want it to be narrowed to 'string.hex'. Is there currently a way to do this in the ArkType system? Many thanks in advance, Chris
4 Replies
TizzySaurus
TizzySaurusβ€’3w ago
You may be able to do something with generics, but I'm not sure ArkType's generic definitions support conditionals like this... you could try
const myValue = type("<t extends 'string' | 'Color', v extends t extends 'Color' ? 'string.hex' : 'string'>", {
type: "t",
value: "v"
})
const myValue = type("<t extends 'string' | 'Color', v extends t extends 'Color' ? 'string.hex' : 'string'>", {
type: "t",
value: "v"
})
Otherwise you can do a top-level narrow. Something like
const stringHex = type("string.hex");

const myValue = type({
type: [stringHex, "|", "string"],
value: "string | string.hex"
}).narrow((data) => {
if (data.type === "Color") {
if (!stringHex.allows(data.value)) {
return ctx.mustBe({key: "value", expected: "a valid hex since 'type' was 'Color'"});
}
}
return true
})
const stringHex = type("string.hex");

const myValue = type({
type: [stringHex, "|", "string"],
value: "string | string.hex"
}).narrow((data) => {
if (data.type === "Color") {
if (!stringHex.allows(data.value)) {
return ctx.mustBe({key: "value", expected: "a valid hex since 'type' was 'Color'"});
}
}
return true
})
Potentially with an else on the data.type === "Color", if you want to disallow hex when type isn't "Color" Not that the types probably won't be narrowed though Maybe you can fix that with .narrow(...).as<NarrowedType>() if it matters to you
πŸŒΊπŸ‡«πŸ‡· Shigu :3 🌺
what you are describing sounds more suited for a discriminated union and wouldn't need all this code
L0xus
L0xusOPβ€’3w ago
thank you so much for the quick response. the generic approach didn't seem to support he conditionals, but the top level narrow did the trick!
Dimava
Dimavaβ€’3w ago
type({
type: "'string'",
value: '"string"
}).or({
type: "'Color'",
value: "string.hex"
})
type({
type: "'string'",
value: '"string"
}).or({
type: "'Color'",
value: "string.hex"
})
Generic is also possible you just need the hkt one

Did you find this page helpful?