Skip to content

Instantly share code, notes, and snippets.

@dazuaz
Last active September 1, 2023 02:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dazuaz/d89fdbe5071f7e68d0871443be27b168 to your computer and use it in GitHub Desktop.
Save dazuaz/d89fdbe5071f7e68d0871443be27b168 to your computer and use it in GitHub Desktop.
Utility to add conditional fields to react hook forms and Zod resolvers
type Rule<T> = {
field: keyof T;
operator: 'is' | 'isNot';
value: T[keyof T];
};
type Condition<T> = {
type: 'show' | 'hide';
rulesMatch: 'any' | 'all';
rules: Rule<T>[];
};
type ConditionsType<T> = Record<keyof T, Condition<T>>
export type Conditions<T> = Partial<Record<keyof T, Condition<T>>>
export function resolveKeysToOmit<T>(data: Partial<T>, conditions: Conditions<T>) {
const keys: (keyof T)[] = []
if (!conditions) return keys
// https://alexharri.com/blog/typescript-structural-typing
Object.entries<Condition<T>>(conditions as ConditionsType<T>).forEach(([key, condition]) => {
if (!condition) return;
const isMatched = condition.rulesMatch === 'all'
? condition.rules.every((r) => {
const value = data[r.field];
return (
(r.operator === 'is' && value === r.value) ||
(r.operator === 'isNot' && value !== r.value)
);
})
: condition.rules.some((r) => {
const value = data[r.field];
return (
(r.operator === 'is' && value === r.value) ||
(r.operator === 'isNot' && value !== r.value)
);
});
if ((condition.type === 'show' && !isMatched) || (condition.type === 'hide' && isMatched)) {
keys.push(key as keyof T);
}
})
return keys
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment