A
arktype2mo ago
Robb

About using a generic pipe

Hello everyone, I am writing a schema in which one of the fields requiredness can be played with. I've come up with this type
const StringWithOptionalModification = type({
value: "string",
mode: "'required' | 'on' | 'off'",
}).pipe((obj) => {
return obj.mode === "off" ? null : obj.value;
});
const StringWithOptionalModification = type({
value: "string",
mode: "'required' | 'on' | 'off'",
}).pipe((obj) => {
return obj.mode === "off" ? null : obj.value;
});
It does the job perfectly well. Now, if I want to use it for a schema, where the value should be sent if the value is null, I can use something like this:
const Profile = type({
username: "string",
password: StringWithOptionalModification,
firstName: "string",
lastName: "string",
}).pipe((s) => {
const { password, ...rest } = s;
const passwordObj = password !== null ? { password } : {};
return {
...rest,
...passwordObj,
};
});
const Profile = type({
username: "string",
password: StringWithOptionalModification,
firstName: "string",
lastName: "string",
}).pipe((s) => {
const { password, ...rest } = s;
const passwordObj = password !== null ? { password } : {};
return {
...rest,
...passwordObj,
};
});
But now, let's say I want to reuse this kind of logic in multiple other schemas. I thought about creating a pipe generator so that only the key needs to be set. Something like this:
const generateEmptyPasswordRemovalPipe = (key: string = "password") => {
return (s: { [key: string]: string | null }) => {
const { [key]: password, ...rest } = s;
const passwordObj = password !== null ? { [key]: password } : {};
return {
...rest,
...passwordObj,
};
};
};
const generateEmptyPasswordRemovalPipe = (key: string = "password") => {
return (s: { [key: string]: string | null }) => {
const { [key]: password, ...rest } = s;
const passwordObj = password !== null ? { [key]: password } : {};
return {
...rest,
...passwordObj,
};
};
};
that would help by rewriting Profile as
const Profile = type({
username: "string",
password: StringWithOptionalModification,
firstName: "string",
lastName: "string",
}).pipe(generateEmptyPasswordRemovalPipe("password"));
const Profile = type({
username: "string",
password: StringWithOptionalModification,
firstName: "string",
lastName: "string",
}).pipe(generateEmptyPasswordRemovalPipe("password"));
But then, the types resulting from the schema seem off. I guess this is more a TypeScript-related question than a Arktype one
1 Reply
ssalbdivad
ssalbdivad2mo ago
Yeah this kind of stuff can definitely be tricky. Especially as your generic logic gets more complex, you will likely have to write the type-level logic manually using conditionals + mapped types to achieve what you want, then cast your implementation to that specified return type. I wrote a bit about this in the docs here: https://arktype.io/docs/faq#why-isnt-my-wrapper-generic-working
ArkType
ArkType Docs
TypeScript's 1:1 validator, optimized from editor to runtime

Did you find this page helpful?