You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TypeScript: a spread call of a destructured local ({...register('x')}) links to an unrelated project function #2962
A call to a destructured local inside a spread ({...register('email')} in JSX, or { ...register('email') } in an object) links by exact name to an unrelated project function with that name. The same call without the spread correctly links nothing.
// auth.tsexportfunctionregister(email: string): Promise<void>{returnPromise.resolve();}// use.tsximport{useForm}from'react-hook-form';exportfunctionobjSpread(){const{ register }=useForm();constprops={ ...register('email')};// line 4returnprops;}exportfunctionjsxSpread(){const{ register }=useForm();return<input{...register('email')}/>;// line 9}exportfunctionjsxSpreadNested(){const{ register }=useForm();return<form><input{...register('email')}/></form>;// line 13}
call
edge on main
expected
line 4 { ...register('email') }
auth.tsregister (resolvedBy: exact-match) ✗
none
line 9 <input {...register('email')} />
auth.tsregister ✗
none
line 13 (nested element)
auth.tsregister ✗
none
Controls that already link nothing (correct):
const { register } = useForm(); register('email'); (no spread)
So the local-binding check that keeps a bare call off cross-file namesakes works for destructured locals, but not when the call follows .... The non-destructured local inside a spread is fine. Only destructuring and spread together fail.
Reproduced on main at 2577601, with CODEGRAPH_KERNEL=0 and with the native kernel. Linux/WSL2, Node 22.23.2. (Commits since then touch only Go, Rust and indexing.)
Why it matters.const { register } = useForm(); … <input {...register('field')} /> is react-hook-form's documented usage, so a React app using it gets one wrong edge per form field. Any project function named register (an auth register(email, password) is common) then shows every form input as a caller.
Expected. Treat the call after ... the same as the plain call: a destructured local in scope shadows cross-file namesakes.
Related: #2949 (another case where a local shadow is missed), #2676 / #2677 (destructured names in JSX children).
Activity