• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* @internal */
2namespace ts.codefix {
3    const fixId = "convertLiteralTypeToMappedType";
4    const errorCodes = [Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0.code];
5
6    registerCodeFix({
7        errorCodes,
8        getCodeActions: function getCodeActionsToConvertLiteralTypeToMappedType(context) {
9            const { sourceFile, span } = context;
10            const info = getInfo(sourceFile, span.start);
11            if (!info) {
12                return undefined;
13            }
14            const { name, constraint } = info;
15            const changes = textChanges.ChangeTracker.with(context, t => doChange(t, sourceFile, info));
16            return [createCodeFixAction(fixId, changes, [Diagnostics.Convert_0_to_1_in_0, constraint, name], fixId, Diagnostics.Convert_all_type_literals_to_mapped_type)];
17        },
18        fixIds: [fixId],
19        getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
20            const info = getInfo(diag.file, diag.start);
21            if (info) {
22                doChange(changes, diag.file, info);
23            }
24        })
25    });
26
27    interface Info {
28        container: TypeLiteralNode,
29        typeNode: TypeNode | undefined;
30        constraint: string;
31        name: string;
32    }
33
34    function getInfo(sourceFile: SourceFile, pos: number): Info | undefined {
35        const token = getTokenAtPosition(sourceFile, pos);
36        if (isIdentifier(token)) {
37            const propertySignature = cast(token.parent.parent, isPropertySignature);
38            const propertyName = token.getText(sourceFile);
39            return {
40                container: cast(propertySignature.parent, isTypeLiteralNode),
41                typeNode: propertySignature.type,
42                constraint: propertyName,
43                name: propertyName === "K" ? "P" : "K",
44            };
45        }
46        return undefined;
47    }
48
49    function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { container, typeNode, constraint, name }: Info): void {
50        changes.replaceNode(sourceFile, container, factory.createMappedTypeNode(
51            /*readonlyToken*/ undefined,
52            factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, factory.createTypeReferenceNode(constraint)),
53            /*nameType*/ undefined,
54            /*questionToken*/ undefined,
55            typeNode,
56            /*members*/ undefined));
57    }
58}
59