'`recast` - adding a properties to an object

I want to modify properties to a particular typescript object with the library recast.

This is the file content:

// /path/to/my/file.ts
...

import somelib from 'somelib';

...

export const theobj:MyType = {
  thekey: {
    prop1: 5,
    prop2: 6
  }
} 

...

I want to remove prop1 and add a prop3 to prop thekey inside the object theobj.

This is my code:

import fs from 'fs';
import * as recast from 'recast';

const source = fs.readFileSync('/path/to/my/file.ts', 'utf-8');

const ts_ast = recast.parse(source, {
     parser: require("recast/parsers/typescript")
});

const all = ts_ast.program.body;

for(const node of all){
    if(node.type === recast.types.namedTypes.ExportNamedDeclaration.toString()){
        const variable_declaration = node.declaration;
        const variable_declarator = variable_declaration.declarations[0];
        if(variable_declarator.id.name === 'theobj'){
            for(const prop_def of variable_declarator.init.properties){
                if(prop_def.key.name === 'theykey'){
                    for(let i = 0; i < prop_def.value.properties.length; i++){
                        const prop_obj = prop_def.value.properties[i];
                        if(prop_def.key.name === 'prop1'){
                            delete prop_def.value.properties[i];
                        }
                    }
                    
                    const id = recast.types.builders.identifier('prop3');
                    const value = recast.types.builders.stringLiteral("'a str value'");
                    const obj_prop = recast.types.builders.objectProperty(id, value);

                    prop_def.value.properties[0].insertAfter(obj_prop);
                    break;
                }
            }
            break;
        }
    }
}

const printed = recast.print(ts_ast).code;
console.log(printed);

Even though the delete works perfectly, the insertAfter does not.

I get:

insertAfter is not a function

I've checked and I saw that prop_def is a Node and not a NodePath. It is NodePath that has the method insertAfter.

In the README it says: "Now do whatever you want to ast. Really, anything at all!", but it doesn't say what are the methods to add a new Node.



Solution 1:[1]

Simplest way to modify AST would be using ?Putout code transformer, I’m working on. Here is Replacer code, it uses ?PutoutScript:

const from = `
    export const theobj:MyType = {
      thekey: {
        prop1: 5,
        prop2: 6
      }
    } 
`

const to = `
    export const theobj:MyType = {
      thekey: {
        prop2: 6,
        prop3: 'a str value',
      }
    } 
`


module.exports.replace = () => ({
    [from]: to
});

Looks this way:

?Putout transform example

You can try it in ?Putout Editor. It uses recast and babel to get things working.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1