microsoft/TypeScript
Refactors and code fixes
The two extension points the language service uses to produce file edits in response to either user-issued commands (refactors) or compiler diagnostics (code fixes).
Distinction
| Refactor | Code fix | |
|---|---|---|
| When offered | Always — based on cursor location | Only when a diagnostic is present at cursor |
| Discovery | getApplicableRefactors(fileName, position, preferences) |
getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences) |
| User intent | Active — "extract this", "convert this" | Reactive — "fix this red squiggle" |
| Grouping | RefactorActionInfo per refactor; user selects an action |
One CodeFixAction per diagnostic; user accepts |
| Applies to | One occurrence | One occurrence (or "fix all" for the same code) |
Both produce FileTextChanges[] via src/services/textChanges.ts.
Code fixes
src/services/codefixes/ contains 80+ code-fix providers. Each is a small TypeScript file that registers itself for one or more error codes:
codefix.registerCodeFix({
errorCodes: [Diagnostics.Cannot_find_name_0.code],
getCodeActions(context) {
/* compute one or more CodeFixActions */
},
fixIds: ['fixCannotFindName'],
getAllCodeActions(context) {
/* fix-all support */
},
});Notable code-fix providers:
| Provider | Role |
| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| importFixes.ts (~115k effective) | The auto-import code fix; resolves "Cannot find name 'X'" by inserting an import |
| addMissingAsync.ts, addMissingAwait.ts | Insert async/await |
| addMissingConst.ts, addMissingDeclareProperty.ts | Annotate variables |
| addOptionalPropertyUndefined.ts | Add | undefinedto optional fields when--exactOptionalPropertyTypes |
| convertFunctionToEs6Class.ts | Rewrite a constructor function as a class |
| convertToAsyncFunction.ts | Promise-then-chain → async/await |
| convertToEsModule.ts | CommonJS → ES module |
| fixAddMissingMember.ts | Suggest a missing class/interface member |
| fixAddMissingParam.ts | Add a missing function parameter |
| fixSpelling.ts | "Did you mean X?" via Levenshtein |
| fixUnusedIdentifier.ts | Remove or prefix-with-_ an unused symbol |
| fixOverrideModifier.ts | Add or remove override |
| inferFromUsage.ts | Infer a parameter type from how the function is called |
| useDefaultImport.ts, splitTypeOnlyImport.ts, convertToTypeOnlyImport.ts | Import-shape adjustments |
| requireInTs.ts | Replace require with import in .ts |
A code fix's description is shown to the user; its changes are applied directly. Many fixes also implement getAllCodeActions(context) for the "fix all in file/project" path; the registry composes these across files.
Refactors
src/services/refactors/ contains ~16 refactor providers. They register via:
refactor.registerRefactor('Extract Symbol', {
kinds: ['refactor.extract.function', 'refactor.extract.constant'],
getAvailableActions(context) {
/* … */
},
getEditsForAction(context, actionName) {
/* … */
},
});The high-impact refactors:
| Refactor | File |
|---|---|
| Extract function / constant | extractSymbol.ts (103k effective) |
| Extract type alias / interface | extractType.ts |
| Move to file | moveToFile.ts (55k effective) |
| Move to new file | moveToNewFile.ts |
| Convert export shape | convertExport.ts, convertImport.ts |
| Convert function ↔ arrow | convertArrowFunctionOrFunctionExpression.ts |
| Convert overloads → single | convertOverloadListToSingleSignature.ts |
| Convert params → object | convertParamsToDestructuredObject.ts |
| Convert string concat ↔ template | convertStringOrTemplateLiteral.ts |
| Convert chain ↔ optional chain | convertToOptionalChainExpression.ts |
| Add/remove arrow braces | addOrRemoveBracesToArrowFunction.ts |
| Generate get/set accessor | generateGetAccessorAndSetAccessor.ts |
| Infer function return type | inferFunctionReturnType.ts |
| Inline variable | inlineVariable.ts |
ChangeTracker
Both extension types build FileTextChanges[] via textChanges.ChangeTracker.with(context, t => { ... }). The tracker offers high-level operations:
t.replaceNode(sourceFile, oldNode, newNode)t.insertNodeAfter(sourceFile, after, newNode)t.deleteNode(sourceFile, node)t.replaceRangeWithText(sourceFile, range, text)t.tryInsertTypeAnnotation(...),t.insertImports(...), …
It applies a printer (emitter.ts's createPrinter) to print synthesised nodes with appropriate formatting that matches the user's existing style.
How a refactor is offered
sequenceDiagram
participant Editor
participant tsserver
participant Service as LanguageService
participant Provider as refactor
Editor->>tsserver: cursor moved
tsserver->>Service: getApplicableRefactors(file, pos)
Service->>Provider: registry → for each provider, getAvailableActions(ctx)
Provider-->>Service: list of ApplicableRefactorInfo
Service-->>tsserver: list
tsserver-->>Editor: code action menu
Editor->>tsserver: user selects action
tsserver->>Service: getEditsForRefactor(...)
Service->>Provider: getEditsForAction
Provider->>Provider: ChangeTracker.with(...)
Provider-->>Service: RefactorEditInfo
Service-->>tsserver: edits
tsserver-->>Editor: apply editsTests
Both refactors and code fixes are exhaustively fourslash-tested. The conventions:
- File names:
codeFixXxx*.tsfor code fixes;refactorXxx*.ts(or descriptive) for refactors. verify.codeFix({ description, newFileContent })— for code fixes.verify.applicableRefactorAvailableAtMarker(...)+verify.fileAfterApplyingRefactorAtMarker(...)— for refactors.
Any new code fix or refactor must include fourslash tests.
Entry points for modification
- Adding a code fix: drop a file under
src/services/codefixes/, callcodefix.registerCodeFix(...). Re-export from_namespaces/ts.codefix.ts. - Adding a refactor: drop a file under
src/services/refactors/, callrefactor.registerRefactor(...). - Improving the change tracker:
src/services/textChanges.ts.
See systems/language-service for the registry, and features/language-service-features for the broader feature catalogue.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.