Ts-morph: How to construct object literals

Created on 15 May 2019  路  7Comments  路  Source: dsherret/ts-morph

So I know that I can create a property like this:

classDeclaration.addProperty({
name: 'foo',
scope: Scope.Private,
type: 'number',
initializer: '4'
});

but how would on build a more complex object:

For example, how would I construct bar in the class below?

class Foo {
    public bar = {
         x: 123,
         y: 'abc',
         z: { one: '1' }
    }
}

I know I could just string build it and set initializer, but I'm wondering if there is a better way?

question

Most helpful comment

This is similar to #320. Basically use the WriterFunctions (kind of experimental, but they'll probably stick around):

import { WriterFunctions } from "ts-morph";

classDeclaration.addProperty({
    name: 'foo',
    scope: Scope.Private,
    type: 'number',
    initializer: WriterFunctions.object({
        x: 123,
        y: writer => writer.quote('abc'),
        z: WriterFunctions.object({
            one: writer => writer.quote('1')
        })
    })
});

You can also create your own writer functions in case you want more control. You'd just have to write something similar to what's done in that WriterFunctions utility class methods. See the definition here. Basically, it does something like this internally:

classDeclaration.addProperty({
    name: 'foo',
    scope: Scope.Private,
    type: 'number',
    initializer: writer => {
        writer.inlineBlock(() => {
            writer.write('x: ').quote('123').newLine();
            writer.write('y: ').quote('abc').newLine();
        });
    }
});

All 7 comments

This is similar to #320. Basically use the WriterFunctions (kind of experimental, but they'll probably stick around):

import { WriterFunctions } from "ts-morph";

classDeclaration.addProperty({
    name: 'foo',
    scope: Scope.Private,
    type: 'number',
    initializer: WriterFunctions.object({
        x: 123,
        y: writer => writer.quote('abc'),
        z: WriterFunctions.object({
            one: writer => writer.quote('1')
        })
    })
});

You can also create your own writer functions in case you want more control. You'd just have to write something similar to what's done in that WriterFunctions utility class methods. See the definition here. Basically, it does something like this internally:

classDeclaration.addProperty({
    name: 'foo',
    scope: Scope.Private,
    type: 'number',
    initializer: writer => {
        writer.inlineBlock(() => {
            writer.write('x: ').quote('123').newLine();
            writer.write('y: ').quote('abc').newLine();
        });
    }
});

Updated my response to use writer.quote('text'). That's a bit better because then it uses the quote character specified in the manipulation settings.

beautiful! thanks!

@dsherret sorry to keep bugging you, but how would I add the as const keyword when using WriterFunctions.object()

public bar = {
         x: 123,
         y: 'abc',
         z: { one: '1' }
    } as const 

That's no problem!

Hmmm never thought about that. You could do this:

initializer: writer => {
    WriterFunctions.object({
        x: 123,
        y: writer => writer.quote('abc'),
        z: WriterFunctions.object({
            one: writer => writer.quote('1')
        })
    })(writer);
    writer.write(" as const");
}

But it would perhaps be better if I added an WriterFunctions.assertion (or assert?) function or if you implemented one yourself. So something like this:

initializer: WriterFunctions.assertion(WriterFunctions.object({
    x: 123,
    y: writer => writer.quote('abc'),
    z: WriterFunctions.object({
        one: writer => writer.quote('1')
    })
}), "const");

Opened #623.

nvm, figured it out

writer => {
                WriterFunctions.object(myObj)(writer);
                writer.write(' as const');
};

Just in case anyone stumbles across this in the future, WriterFunctions has been deprecated. Use Writers, instead. :)

Behold, my mighty hack:

this.viewStore = this.serverEngine.addVariableStatement({
    declarationKind: VariableDeclarationKind.Const,
    declarations: [{name: "ViewStore", initializer: Writers.object({})}]
}).getDeclarations()[0].getInitializer() as ObjectLiteralExpression;

this.viewStore.addPropertyAssignment({
    name: "someProp",
    initializer: "'ur mum'"
});
Was this page helpful?
0 / 5 - 0 ratings