ts-morph-structures

When to use this library, versus direct ts-morph interaction

First, I’ll direct you to ts-morph’s Performance page, where the first tip is “work with structures instead”. I couldn’t agree more. My own experience suggested quadratic time performance in modifying the same file repeatedly using ts-morph directly. (Admittedly this was around a year ago.)

  1. If you trust yourself to write your output without ts-morph, do so.
  2. If you are doing small tweaks without needing to build new AST nodes, use ts-morph.
  3. If your task is really simple and short to do with ts-morph, use ts-morph.
  4. If you are creating new AST nodes, consider ts-morph-structures to feed ts-morph.
  5. If you are doing complex manipulations, consider ts-morph-structures to replace nodes in ts-morph.

This really boils down to “the right tool for the job”. Namely, “is it better to do it by hand, or to combine inputs and functions to create an output?”

For example, if you have an existing interface (especially one you do not control) and you want to build a class from it, ts-morph-structures provides a type-to-class set of tools to help you do so. Doing this directly in ts-morph is possible but complex:

On the other hand, if all you’re doing is setting a return type on a class method, maybe ts-morph-structures isn’t the right tool for this. You can do this by hand:

const returnType = new TypeArgumentedTypeStructureImpl(
  LiteralTypeStructureImpl.get("Pick"), [
    LiteralTypeStructureImpl.get("[]"),
    new UnionTypeStructureImpl([
      new PrefixOperatorsTypeStructureImpl(
        ["keyof", "readonly"],
        new TupleTypeStructureImpl([]), // same thing as "[]"
      ),
      StringTypeStructureImpl.get("sort")
    ])
  ]
);

myClass.getMethodOrThrow("foo").setReturnType(returnType.writerFunction);

You can use parseLiteralType():

myClass.getMethodOrThrow("foo").setReturnType(
  parseLiteralType(`Pick<[], keyof readonly [] | "sort">`).writerFunction
);

Or you could set the type directly as ts-morph allows:

myClass.getMethodOrThrow("foo").setReturnType(`Pick<[], keyof readonly [] | "sort">`);

The first option is cumbersome in a direct case like this. It’s more useful when you want to modify the composite type along the way.

Where this project really shines

Where this project doesn’t help much