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 local that shadows a project import is ignored from a nested arrow; the call links to the import #2949
If a function declares a local that shadows a name the file imports from a project file, a call to that name from a nested arrow links to the import instead of the local. The same code importing from a package resolves correctly in every shape, thanks to #2855.
// lib.tsexportfunctionskipString(j: number): number{returnj+1;}// use.tsimport{skipString}from'./lib';exportfunctionscanA(s: string){constskipString=(j: number): number=>j+2;returnskipString(0);// line 4}exportfunctionscanB(s: string){functionskipString(j: number): number{returnj+3;}returnskipString(0);// line 8}exportfunctionscanC(s: string){returnskipString(0);}// line 10exportfunctionscanD(s: string){constskipString=(j: number): number=>j+2;constskipValue=(j: number): number=>skipString(j);// line 13returnskipValue(0);}exportfunctionscanE(s: string){functionskipString(j: number): number{returnj+3;}constskipValue=(j: number): number=>skipString(j);// line 18returnskipValue(0);}
call
from './lib' (project)
from 'some-pkg' (package)
expected
line 4 (scanA, own local)
no edge
local at line 3
local
line 8 (scanB, own local function)
no edge
local at line 7
local
line 10 (scanC, no shadow)
lib.tsskipString
none (package)
the import
line 13 (nested arrow, const shadow)
lib.tsskipString (resolvedBy: import) ✗
local at line 12
local
line 18 (nested arrow, function shadow)
lib.tsskipString (resolvedBy: import) ✗
local at line 17
local
The two marked rows are wrong edges. The two "no edge" rows for the project import are missing edges rather than wrong ones. The import resolver appears to check for a shadow only in the calling node's own scope, not in the functions around it, and only the package-import path (#2855) prefers the local.
Reproduced on main at 31ec908 (6162d872 since then only touches the watcher), with CODEGRAPH_KERNEL=0. Linux/WSL2, Node 22.23.2.
In this repo.src/resolution/frameworks/react.ts has the same shape. readObjectValue declares const skipString (lines 392–396), and the nested skipValue arrow calls it at line 401. That call links to skipString in object-literal.ts, which react.ts imports. The same shape occurs again at line 441, against a second local skipString declared at line 432. I found these by checking every TS calls edge against the TypeScript checker.
Expected. Apply the same lexical shadow check to a name imported from a project file as to one imported from a package: the innermost binding in scope at the call wins, including bindings in enclosing functions.
Edited 2026-11-04: re-checked on main at f72c9d2 (with CODEGRAPH_KERNEL=0 and with the native kernel, Node 22.22.2): still reproduces. Added: scanA and scanB get no edge at all, to the local or anywhere, which is a separate gap. Nothing else changed.
Activity