typescript - Hur man lägger till/tar bort en modifierare till/från ett uttalande?


Jag använder TypeScript-kompilatorn API för att transformera TypeScript-kod, men en sak jag inte riktigt har klurat ut är hur man lägger till/tar bort modifierare på ett generiskt sätt. Det närmaste jag har kommit är detta

function removeDeclareModifier(s) {
    let modifiers;
    // Remove declare modifiers
    if (s.modifiers) {
        modifiers = s.modifiers.filter(m => m.kind !== ts.SyntaxKind.DeclareKeyword);
    } else {
        return s;
    }

    if (ts.isVariableStatement(s)) {
        return ts.updateVariableStatement(s, modifiers, s.declarationList);
    } else if (ts.isTypeAliasDeclaration(s)) {
        return ts.updateTypeAliasDeclaration(s, s.decorators, modifiers, s.name, s.typeParameters, s.type);
    } else if (ts.isInterfaceDeclaration(s)) {
        return ts.updateInterfaceDeclaration(s, s.decorators, modifiers, s.name, s.typeParameters, s.heritageClauses, s.members);
    } else if (ts.isEnumDeclaration(s)) {
        return ts.updateEnumDeclaration(s, s.decorators, modifiers, s.name, s.members);
    } else if (ts.isClassDeclaration(s)) {
        return ts.updateClassDeclaration(s, s.decorators, modifiers, s.name, s.typeParameters, s.heritageClauses, s.members);
    } else if (ts.isFunctionDeclaration(s)) {
        return ts.updateFunctionDeclaration(s, s.decorators, modifiers, s.asteriskToken, s.name, s.typeParameters, s.parameters, s.type, s.body);
    }
    return s;
}

men detta verkar verkligen ordrikt, saknar förmodligen en massa fall och är mycket benäget att gå sönder när en av signaturerna ändras. Jag har hittat ett annat svar där det föreslogs att ersätta modifiers-arrayen, men s.modifiers är skrivskyddad, så TypeScript låter mig inte göra det.

Finns det inget bättre sätt att bara uppdatera modifierarna utan att återskapa hela AST-noden?

Svar #1

Du kan använda ts.transform

https://github.com/madou/typescript-transformer-handbook#writing-your-first-transformer

  const result = ts.transform<ts.SourceFile>(sourceFiles, [transformer]);

  function transformer<T extends ts.Node>(context: ts.TransformationContext) {
    return (rootNode: T) => {
        function visit(sourceFile: ts.Node): ts.Node {

            return ts.visitEachChild(sourceFile, (node) => converNode(node), context);
        }

        function converNode(node: ts.Node) {

            return ts.visitEachChild(node, visitChilds, context);

            function visitChilds(child: ts.Node): ts.Node | undefined {
                if (child.kind == ts.SyntaxKind.ExportKeyword) return undefined;
                if (child.kind == ts.SyntaxKind.AsyncKeyword) return undefined;

                return ts.visitEachChild(child, visitChilds, context);
            }

         
        }

        return ts.visitNode(rootNode, visit);
    };
}