Skip to content

Commit d296f3d

Browse files
committed
feat: Enable extractTypeInferName by default with ability to specify name pattern via codeActions.extractTypeInferNamePattern
1 parent 01f5f8c commit d296f3d

2 files changed

Lines changed: 21 additions & 8 deletions

File tree

src/configurationType.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,14 +480,21 @@ export type Configuration = {
480480
displayAdditionalInfoInCompletions: boolean
481481
/**
482482
* Wether to try to infer name for extract type / interface code action
483-
* e.g. `let foo: { a: number }` -> `type FooType = { a: number }`
484-
*
485-
* Experimental and *will be enabled by default* once its:
486-
* 1. More configurable and rename is called
487-
* 2. Logic to avoid name conflicts
488-
* @default false
483+
* e.g. `let foo: { a: number }` -> `type Foo = { a: number }`
484+
* @default true
489485
*/
490486
'codeActions.extractTypeInferName': boolean
487+
/**
488+
* Use `{{name}}` as a placeholder to insert inferred name (possibly with _{i} at the end)
489+
*
490+
* @default "{{name}}"
491+
*/
492+
'codeActions.extractTypeInferNamePattern':
493+
| string
494+
| {
495+
typeAlias: string
496+
interface: string
497+
}
491498
}
492499

493500
// scrapped using search editor. config: caseInsesetive, context lines: 0, regex: const fix\w+ = "[^ ]+"

typescript/src/codeActions/improveBuiltin.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default (
99
c: GetConfig,
1010
prior: ts.RefactorEditInfo,
1111
): ts.RefactorEditInfo | undefined => {
12+
if (actionName === 'Extract to typedef') return
1213
const extractToInterface = actionName === 'Extract to interface'
1314
if (c('codeActions.extractTypeInferName') && (actionName === 'Extract to type alias' || extractToInterface)) {
1415
const changeFirstEdit = (oldText: string, newTypeName: string) => {
@@ -25,12 +26,15 @@ export default (
2526
if (!node) return
2627
if (ts.isAsExpression(node) || ts.isSatisfiesExpression(node)) node = node.parent
2728
if (ts.isVariableDeclaration(node) || ts.isParameter(node) || ts.isPropertyAssignment(node) || ts.isPropertySignature(node)) {
28-
let isWithinType = ts.isPropertySignature(node)
29+
const isWithinType = ts.isPropertySignature(node)
2930
if (ts.isIdentifier(node.name)) {
3031
const identifierName = node.name.text
3132
if (!identifierName) return
3233
let typeName = identifierName[0]!.toUpperCase() + identifierName.slice(1)
33-
if (!isWithinType) typeName += 'Type'
34+
const namePatternRaw = c('codeActions.extractTypeInferNamePattern')
35+
const namePatternSelected = typeof namePatternRaw === 'object' ? namePatternRaw[extractToInterface ? 'interface' : 'typeAlias'] : namePatternRaw
36+
// apply name pattern to type name
37+
typeName = tsFull.getUniqueName(namePatternSelected.replaceAll('{{name}}', typeName), sourceFile as FullSourceFile)
3438
const newFileEdit: ts.FileTextChanges = {
3539
fileName,
3640
textChanges: textChanges.map((textChange, i) => {
@@ -40,6 +44,8 @@ export default (
4044
}
4145
return {
4246
edits: [newFileEdit],
47+
renameFilename: fileName,
48+
renameLocation: tsFull.getRenameLocation([newFileEdit], fileName, typeName, /*preferLastLocation*/ false),
4349
}
4450
}
4551
}

0 commit comments

Comments
 (0)