.ts, .mts, .cts), and TSX (.tsx).
What it detects
- Functions: declarations, expressions, and arrow functions all become
Function - Methods:
method_definitionbecomesMethod - Classes: declarations and expressions become
Class - Interfaces:
interface_declarationbecomesInterface - Types:
type_alias_declarationbecomesTypeDef - Enums:
enum_declarationbecomesEnum - Imports:
import_statementbecomesImport, withNamedImports/NamespaceImportchildren - Exports:
export_statementandexport_defaultbecomeExport - Variables:
variable_declaration(var) andlexical_declaration(let/const) becomeVariable, labeled with the declarator name - JSX: elements, attributes, and expressions are their own concepts
- Control flow: if / for / while / switch / try / return / throw
- Literals and expressions: strings, numbers, templates, regex, booleans, objects, arrays, calls, member access, operators, await / yield
Node type mapping
Node types without a mapping keep their raw tree-sitter type name.
Most declaration labels come from Tree-sitter’s
name field. For var, let,
and const, the Rust label extractor reads the first variable_declarator child.
The implementation lives in crates/differens-tiers/src/code/labels.rs.
Example: a TypeScript refactor
RenamecomputeTotal to calculateTotalAmount, add a discount parameter, and
change the function body:
before.ts
after.ts
differens before.ts after.ts:
--format=json to read each action. When comparing directories or repository
revisions, Differens can also detect moves across files. Modified declaration
moves must keep the same name; moving and renaming a function together may
produce an addition and a removal.
Example: move and edit a helper across files
Compare two directory snapshots. The destination module already exists, and the helper keeps its name while its body changes. This separates a modified move from the within-file rename example above:old/src/utils.ts
new/src/utils.ts
old/src/pricing.ts
new/src/pricing.ts
edited for a modified
declaration move, and JSON exposes modified: true. The move summary pairs the
supported declaration edits. Other edits, such as a
new import, remain in the report. Renaming the helper during the move can prevent
that pairing; use the original per-file JSON actions when investigating it.
Known limitations
- Multi-declarator variables:
const a = 1, b = 2labels theVariablewith the first declarator’s name only. - Interface members are distinct concepts:
property_signature,call_signature, andmethod_signatureare separate concepts, not a unified “member”. - JSX text is a flat node:
jsx_textcollapses contiguous text, so inline formatting changes inside JSX text can read as a single update. - No type-flow inference: the extractor does not distinguish a value used as a type from a type used as a value.
- Unmapped node types pass through: anything outside the map keeps its raw tree-sitter type name.