Last active
September 1, 2023 02:32
-
-
Save dazuaz/d89fdbe5071f7e68d0871443be27b168 to your computer and use it in GitHub Desktop.
Utility to add conditional fields to react hook forms and Zod resolvers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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