Prompt
Prevent undefined/void/falsy values from becoming accidental runtime states.
Apply these rules:
- Eliminate transient
undefined: If a value can be absent (e.g., localStorage, optional query data), wire an explicitdefaultValueso hooks/state initialize to a concrete value and consumers never render an “undefined first frame”.- Prefer setting the
useStateinitial value fromdefaultValueinside the utility hook rather than letting it beundefinedand patching later.
- Prefer setting the
- Guard globals by environment: Never assume browser APIs exist—use a shared “is server/client” check before touching
window/DOM. - Treat
void/no-arg and falsy as testable cases: When designing/using optional variables or cached data, add type and runtime tests forvoid(no variables) and for falsy cached values (e.g.,'',0,false) so “absent” isn’t conflated with “no result”. - Don’t rely on
undefinedbeing “missing” during key/hash matching: If keys are serialized/hashed (e.g., viaJSON.stringify) or displayed via hashes,undefinedmay be removed, making different logical keys collide or fail to match.- Prefer key shapes where absence is explicit (e.g., use a dedicated sentinel or omit the property at the call site) and document/align hashing with comparison semantics.
Example (default to avoid initial undefined):
function useLocalStorage<T>(key: string, defaultValue: T) {
const [value, setValue] = React.useState<T>(() => {
const raw = localStorage.getItem(key)
return raw == null ? defaultValue : (JSON.parse(raw) as T)
})
// ...sync back to localStorage
return [value, setValue] as const
}
If a behavior constraint exists (e.g., a function must not return undefined), encode it in types and tests—don’t “test” impossible states.