Summary
The TypeScript extractor never indexes interface members. interface_declaration is captured, but the method_signature and property_signature nodes inside it are not, so an interface's methods and properties do not exist in the graph.
The consequence is larger than it first looks: for any codebase whose platform/SDK API is expressed as interface method signatures in a .d.ts (very common — a vendored platform SDK, a generated client, @types/*), every call site through that API is invisible, because there is no declaration node for the call edge to attach to.
Java and C# are unaffected: in those grammars interface methods reuse method_declaration, which is already in their methodTypes. TypeScript is uniquely affected because tree-sitter-typescript uses distinct method_signature / property_signature node types.
Repro
api.d.ts, the whole project:
export interface PlatformContext {
deleteQueueCustomAck(queueName: string, thingId: number): void
createQueueCustomAckKey(queueName: string, thingId: number): void
readonly tenantId: string
}
$ codegraph init
● 2 nodes, 1 edges
Nodes by Kind:
file 1
interface 1
$ codegraph node PlatformContext
**PlatformContext** (interface) ← found
$ codegraph node deleteQueueCustomAck
Symbol "deleteQueueCustomAck" not found in the codebase
$ codegraph node tenantId
Symbol "tenantId" not found in the codebase
Zero method and zero property nodes for an interface that declares two methods and a property.
Note the members are found if a class implements them — the class's method_definition nodes are picked up — which is why this is easy to miss. An interface-only declaration file (.d.ts) exposes it cleanly.
Root cause
src/extraction/languages/typescript.ts:
methodTypes: ['method_definition', 'public_field_definition'],
interfaceTypes: ['interface_declaration'],
// no propertyTypes
Neither method_signature nor property_signature appears anywhere in the file (still true on main as of today).
The traversal side is already correct — isInsideClassLikeNode() in src/extraction/tree-sitter.ts already lists 'interface':
return (parentNode.kind === 'class' ||
parentNode.kind === 'struct' ||
parentNode.kind === 'interface' || // already handled
...);
So the walker will attach members to an interface parent as soon as the node types are declared. This looks like a config omission rather than a design decision.
Suggested fix
methodTypes: ['method_definition', 'public_field_definition', 'method_signature'],
propertyTypes: ['property_signature'],
Verified effect
Applied to a local v1.4.1 install:
|
before |
after |
| The 5-line repro above |
2 nodes, 0 methods |
5 nodes, 2 methods, 1 property |
A 500KB vendor platform .d.ts (interfaces only) |
338 nodes, 247 interfaces, 0 methods |
3,892 nodes, 3,507 methods, 51 properties |
| A real 5,722-file TS monorepo, full re-index |
99,046 nodes |
115,406 nodes; property 4,454 → 20,741 |
Re-index cost was unchanged in practice (47s for the monorepo).
Related but distinct
Secondary note (not part of this issue)
For the .d.ts-in-node_modules case specifically, the patch alone is not enough, because node_modules is a hard-coded ignore that neither codegraph.json include nor includeIgnored overrides. Indexing the package as its own project works as a workaround. Mentioning only because it is the most common place platform interfaces live; happy to open that separately if it is worth its own discussion.
Environment
- CodeGraph 1.4.1 (behaviour confirmed unchanged on
main)
- macOS, TypeScript sources
Summary
The TypeScript extractor never indexes interface members.
interface_declarationis captured, but themethod_signatureandproperty_signaturenodes inside it are not, so an interface's methods and properties do not exist in the graph.The consequence is larger than it first looks: for any codebase whose platform/SDK API is expressed as interface method signatures in a
.d.ts(very common — a vendored platform SDK, a generated client,@types/*), every call site through that API is invisible, because there is no declaration node for the call edge to attach to.Java and C# are unaffected: in those grammars interface methods reuse
method_declaration, which is already in theirmethodTypes. TypeScript is uniquely affected because tree-sitter-typescript uses distinctmethod_signature/property_signaturenode types.Repro
api.d.ts, the whole project:Zero
methodand zeropropertynodes for an interface that declares two methods and a property.Note the members are found if a class implements them — the class's
method_definitionnodes are picked up — which is why this is easy to miss. An interface-only declaration file (.d.ts) exposes it cleanly.Root cause
src/extraction/languages/typescript.ts:Neither
method_signaturenorproperty_signatureappears anywhere in the file (still true onmainas of today).The traversal side is already correct —
isInsideClassLikeNode()insrc/extraction/tree-sitter.tsalready lists'interface':So the walker will attach members to an interface parent as soon as the node types are declared. This looks like a config omission rather than a design decision.
Suggested fix
Verified effect
Applied to a local v1.4.1 install:
.d.ts(interfaces only)property4,454 → 20,741Re-index cost was unchanged in practice (47s for the monorepo).
Related but distinct
importsedge lands on a class property or interface method that merely shares the imported name (import path from 'node:path'→SomeType::path) #1537 — animportsedge landing on an interface method that shares a name. That one implies interface methods are expected to be addressable; this issue is why they are not, in TS.Secondary note (not part of this issue)
For the
.d.ts-in-node_modulescase specifically, the patch alone is not enough, becausenode_modulesis a hard-coded ignore that neithercodegraph.jsonincludenorincludeIgnoredoverrides. Indexing the package as its own project works as a workaround. Mentioning only because it is the most common place platform interfaces live; happy to open that separately if it is worth its own discussion.Environment
main)