1. Project Overview & Quickstart (dsherret/ts-morph)
File: README.md
Monorepo for ts-morph and related projects.
Packages
- ts-morph - TypeScript Compiler API wrapper. Provides an easier way to programmatically navigate and manipulate TypeScript and JavaScript code.
- @ts-morph/bootstrap - Separate library for getting quickly setup with the Compiler API.
Resources
File: Readme.md
Monorepo for ts-morph and related projects.
Packages
- ts-morph - TypeScript Compiler API wrapper. Provides an easier way to programmatically navigate and manipulate TypeScript and JavaScript code.
- @ts-morph/bootstrap - Separate library for getting quickly setup with the Compiler API.
Resources
File: readme.md
Monorepo for ts-morph and related projects.
Packages
- ts-morph - TypeScript Compiler API wrapper. Provides an easier way to programmatically navigate and manipulate TypeScript and JavaScript code.
- @ts-morph/bootstrap - Separate library for getting quickly setup with the Compiler API.
Resources
File: docs/details/ambient.md
title: Ambient
Ambient
Certain nodes in TypeScript can be ambient. For example, all nodes within a declaration file are ambient.
Testing if ambient
Use isAmbient():
classDeclaration.isAmbient(); // returns: booleanThis will do several checks to see if it's an ambient declaration.
`declare` keyword
Check for the declare keyword:
classDeclaration.hasDeclareKeyword(); // returns: booleanOr get the declare keyword if it exists:
classDeclaration.getDeclareKeyword();Or set if it has a declare keyword:
classDeclaration.setHasDeclareKeyword(true);
classDeclaration.setHasDeclareKeyword(false);File: docs/details/async.md
title: Async
Async
Certain nodes in TypeScript can have an async keyword modifier.
Is async
A node can be tested if it's async using the isAsync() method:
functionDeclaration.isAsync(); // returns: boolean`async` keyword
Get the async keyword if it exists:
functionDeclaration.getAsyncKeyword();Set async
Set if the declaration is async using setIsAsync:
functionDeclaration.setIsAsync(true);File: docs/details/classes.md
title: Classes
Class Declarations
Class declarations can be retrieved from source files, namespaces, or function bodies:
const classes = sourceFile.getClasses();
const class1 = sourceFile.getClass("Class1");
const firstClassWithConstructor = sourceFile.getClass(c => c.getConstructors().length > 0);Name
It's important to note that class declarations may not have a name. For example:
export default class {
// etc...
}For this reason, the methods like .getName() and .getNameNode() are nullable on ClassDeclaration.
Add/Insert
Add or insert classes to a source file, namespace, or function like declarations by calling addClass(), addClasses(), insertClass(), or insertClasses().
const classDeclaration = sourceFile.addClass({
name: "ClassName",
});Remove
Call .remove():
classDeclaration.remove();Extends expression
Will return ExpressionWithTypeArguments | undefined:
const extendsExpression = classDeclaration.getExtends();Set the extends expression:
classDeclaration.setExtends("BaseClass");Remove it:
classDeclaration.removeExtends();Implements expressions
Will return ExpressionWithTypeArguments[]:
const implementsExpressions = classDeclaration.getImplements();Add or insert implements expressions:
classDeclaration.addImplements("Named");
classDeclaration.addImplements(["Named", "Aged"]);
classDeclaration.insertImplements(1, "Named");
classDeclaration.insertImplements(1, ["Named", "Aged"]);Remove an expression:
classDeclaration.removeImplements(0); // index
classDeclaration.removeImplements(classDeclaration.getImplements()[0]); // nodeBase Types
Get the base types:
const baseTypes = classDeclaration.getBaseTypes(); // returns: Type[]This is useful to use if you don't know if the class could possibly extend a mixin or a class.
Base Class
Get the base class:
const baseClass = classDeclaration.getBaseClass(); // returns: ClassDeclaration | undefinedNote: This is not a useful method to use if the base could possibly be a mixin. If you expect mixins, then use .getBaseTypes().
Derived Classes
Will return all the class declarations that derive from the current class:
const derivedClasses = classDeclaration.getDerivedClasses();Constructor
Constructors can be retreived via getConstructors. This returns all the constructors in an ambient context, but will only return the
implementation constructor otherwise.
const constructors = classDeclaration.getConstructors();Add or insert a constructor or constructors by calling addConstructor(), addConstructors(), insertConstructor(), or insertConstructors().
const ctor = classDeclaration.addConstructor({
/* options like parameters may go here */
});Methods
Get instance methods:
const instanceMethods = classDeclaration.getInstanceMethods();
const myMethod = classDeclaration.getInstanceMethod("myMethod");
const firstMethodWith2Params = classDeclaration.getInstanceMethod(m => m.getParameters().length === 2);Get the static methods:
const staticMethods = classDeclaration.getStaticMethods();
const myStaticMethod = classDeclaration.getStaticMethod("myMethod");
const firstStaticMethodWith2Params = classDeclaration.getStaticMethod(m => m.getParameters().length === 2);Add/Insert
Add or insert methods by using insertMethods(), insertMethod, addMethod, or addMethods:
const method = classDeclaration.addMethod({ isStatic: true, name: "myMethod", returnType: "string" });Remove
Call .remove():
method.remove();Properties
Get the instance properties (includes parameter properties):
const instanceProperties = classDeclaration.getInstanceProperties();
const myProperty = classDeclaration.getInstanceProperty("myProperty");
const myStringProperty = classDeclaration.getInstanceProperty(p =>
Node.isPropertyDeclaration(p) && p.getType().getText() === "string");Get the static properties:
const staticProperties = classDeclaration.getStaticProperties();
const myStaticProperty = classDeclaration.getStaticProperty("myStaticProperty");
const myStaticStringProperty = classDeclaration.getStaticProperty(p =>
Node.isPropertyDeclaration(p) && p.getType().getText() === "string");Add/Insert
Add or insert properties by using insertProperties(), insertProperty, addProperty, or addProperties:
const property = classDeclaration.addProperty({
isStatic: true,
name: "prop",
type: "string",
});Add or insert get accessors by using insertGetAccessors(), insertGetAccessor, addGetAccessor, or addGetAccessors:
const getAccessor = classDeclaration.addGetAccessor({
name: "someNumber",
returnType: "number",
statements: ["return 5;"],
});Add or insert set accessors by using insertSetAccessors(), insertSetAccessor, addSetAccessor, or addSetAccessors:
const setAccessor = classDeclaration.addSetAccessor({
name: "someNumber",
parameters: [{ name: "value", type: "number" }],
statements: ["_someNumber = value;"],
});Remove
Call .remove():
propertyDeclaration.remove();Get members
Get all the members regardless of whether static or instance:
const allMembers = classDeclaration.getMembers();Get instance members including parameter properties:
const instanceMembers = classDeclaration.getInstanceMembers();Get static members:
const staticMembers = classDeclaration.getStaticMembers();Extracting an Interface
An interface declaration structure can be extracted from a class by calling classDeclaration.extractInterface(). For example:
// the passed in name is optional and defaults to the class name
const interfaceStructure = classDeclaration.extractInterface(`I${classDeclaration.getName()}`);Alternatively the static interface declaration structure of a class can be extracted by calling:
const interfaceStructure = classDeclaration.extractStaticInterface(`${classDeclaration.getName()}Static`);Abstract
Nodes on a class may be abstract.
Get if it's abstract:
method.isAbstract(); // returns: booleanGet the abstract keyword:
method.getAbstractKeyword(); // returns: node | undefinedSet if abstract:
method.setIsAbstract(true); // set as abstract
method.setIsAbstract(false); // set as not abstractConstructors
Constructors implement common functions found on function like declarations, but also include a scope.
Methods
Explore the functionality available via auto-complete.
Properties
Explore the functionality available via auto-complete.
Get Accessors
If it exists, get the corresponding set accessor:
const setAccessor = getAccessor.getSetAccessor();Set Accessors
If it exists, get the corresponding get accessor:
const getAccessor = setAccessor.getGetAccessor();File: docs/details/comments.md
title: Comments
Comments
ts-morph parses out certain kinds of comments to make them easier to work with. This breaks away from the behaviour in the compiler API because although comments are not very important for compiling, they can be important for programmatic refactoring tasks.
- Comment Ranges - Comments the compiler api parses out.
- Comment Nodes - Comments ts-morph parses out in certain scenarios. They extend from
ts.Node.
Comment Ranges
Comment ranges are not part of the AST and are generated on request.
- Leading: Comments that preceed the node after the previous significant tokenโbetween
node.getPos()andnode.getStart(). - Trailing: Comments following the node before the next siginificant token or newline.
WARNING: Since comments are generated on demand and not part of the AST, using one after a
subsequent manipulation to the source file will throw an error.
Retrieving
Leading and trailing comment ranges can be retrieved from any node by calling:
const leadingComments = node.getLeadingCommentRanges();
const trailingComments = node.getTrailingCommentRanges();Information
Once you have a comment range, there are several self explanatory methods:
.getKind()- ReturnsSyntaxKind.SingleLineCommentTriviaorSyntaxKind.MultiLineCommentTrivia..getPos()- Position..getEnd()- End position..getWidth()- Width (end - pos).getText()- Text..wasForgotten()- Returns true if the node was forgotten because a manipulation occured to the source file or its associated node was forgotten.
More Details
Read more about comments in the compiler API documentation here: https://github.com/Microsoft/TypeScript/wiki/Architectural-Overview#trivia
Comment Nodes
These are nodes ts-morph parses out. They do not include all comments, but only the first comment on a line if there are no significant tokens on that line and only in certain contexts (ex. source file statements, class declaration body, function body, namespace body, etc..).
For example, in the following scenario:
// do something
functionCall(); // ok...only the first comment will be parsed out. The second comment is considered a trailing comment range of the function call.
Retrieving
Comment ranges can be retrieved using various #getXWithComments() methods.
For example:
sourceFile.getStatementsWithComments();
classDec.getMembersWithComments();
interfaceDec.getMembersWithComments();
objectLiteralExpression.getPropertiesWithComments();They also may appear in the results of #getChildren() in certain scenarios. For example:
const children = sourceFile.getChildSyntaxListOrThrow().getChildren();This extends the behaviour of the compiler API.
Why?
The reason this is done is to make inserting before or after comments possible. For example, given the following source file:
// 1
// 2
functionCall();It is possible to insert a statement after the first comment by specifying sourceFile.insertStatement(1, "// new comment");, which would modify the source file to be:
// 1
// new comment
// 2
functionCall();Removing Comments
To remove a comment node, call #remove() on it:
sourceFile.getStatementsWithComments()[0].remove();This will remove the comment and any of its trailing comment nodes.
Trailing comment ranges of comment nodes
Comment nodes may have trailing comment ranges. For example, given the following source file:
/* 1 */ // 2...the text /* 1 */ is considered the comment node, while // 2 is the trailing comment range. // 2 can be retrieved with the following code:
const secondComment = sourceFile.getStatementsWithComments()[0].getTrailingCommentRanges()[0];File: docs/details/decorators.md
title: Decorators
Decorators
Decorators can be retrieved from class related nodes by calling the getDecorators() method.
const decorators = classDeclaration.getDecorators();Name
Get the name or fully qualified name of a decorator by using the getName() or getFullName() functions respectively.
For example, given the following code:
@obj.decorator
class Identifier {
}The following happens:
decorator.getName(); // "decorator"
decorator.getFullName(); // "obj.decorator"Decorator factory
Decorators with parenthesis (ex. @decorator(3)) are decorator factories, while decorators without (ex. @decorator) are not.
decorator.isDecoratorFactory(); // returns: booleanSet as a decorator factory or not:
decorator.setIsDecoratorFactory(true);Arguments
Get the decorator's arguments by calling .getArguments():
const args = decorator.getArguments(); // returns: Expression[]Add and insert via .addArgument(...), .insertArguments(...), .addArgument(...), or .addArguments(...).
const args = decorator.insertArguments(1, ["5", "6"]);And remove them by calling .removeArgument():
// specify the index
decorator.removeArgument(0);
// or specify the argument node
decorator.removeArgument(args[0]);Type arguments
Get the decorator's type arguments by calling .getTypeArguments():
const typeArgs = decorator.getTypeArguments(); // returns: TypeNode[]Add and insert via .insertTypeArgument(...), .insertTypeArguments(...), .addTypeArgument(...), or .addTypeArguments(...).
const typeArgs = decorator.insertTypeArguments(1, ["string", "number"]);And remove them by calling .removeTypeArgument():
// specify the index
decorator.removeTypeArgument(0);
// or specify the type argument node
decorator.removeTypeArgument(typeArgs[0]);Call expression
Decorator factories are call expressions. Get the call expression by calling:
const callExpression = decorator.getCallExpression(); // returns: CallExpression | undefinedAdd/Insert decorators
Decorators can be added or inserted by calling addDecorator(decorator), addDecorators(decorators), insertDecorator(index, decorator), or insertDecorators(index, decorators).
For example:
classDeclaration.addDecorator({
name: "MyDecorator",
arguments: ["3", `"some string"`],
});Remove decorators
Call .remove():
decorator.remove();File: docs/details/documentation.md
title: JS Docs
JS Docs
Certain nodes can have JS docs. For example:
/**
* Gets the name.
* @param person - Person to get the name from.
*/
function getName(person: Person) {
// ...
}Get all JS doc nodes
Get all the JS doc nodes by using getJsDocs():
functionDeclaration.getJsDocs(); // returns: JSDoc[]Add/insert docs
Add or insert JS doc comments using the addJsDoc(), addJsDocs(), insertJsDoc(), and insertJsDocs() methods.
For example:
// adds /** Some description... */
const docNode = classDeclaration.addJsDoc({
});
// or to force it to be multi-line, add a newline to the front of the string
classDeclaration.addJsDoc({
});
// or with tags
classDeclaration.addJsDoc({
tags: [{
tagName: "param",
text: "value - My value.",
}],
});JSDoc Nodes
Get the description:
// Getting the node from the example at the top of this file.
const jsDoc = functionDeclaration.getJsDocs()[0];
jsDoc.getDescription(); // returns string: "Gets the name."Get the tags:
const tags = jsDoc.getTags();
tags[0].getText(); // "@param person - Person to get the name from."Get the inner text (the text without the surrounding comment):
jsDoc.getInnerText(); // "Gets the name.\n@param person - Person to get the name from."File: docs/details/enums.md
title: Enums
Enums
Enums can be retrieved from source files, namespaces, or function bodies:
const enums = sourceFile.getEnums();
const enum1 = sourceFile.getEnum("Enum1");
const enum2 = sourceFile.getEnum(e => e.getMembers().length === 5);Add/Insert
Add or insert enums to a source file, namespace, or function like declarations by calling addEnum(), addEnums(), insertEnum(), or insertEnums().
const enumDeclaration = sourceFile.addEnum({
name: "EnumName",
members: [{
name: "member",
}],
});Remove
Call .remove():
enumDeclaration.remove();Get all members
Use getMembers():
const members = enumDeclaration.getMembers();Get member
Use getMember():
const member1 = enumDeclaration.getMember("member1");
const member2 = enumDeclaration.getMember(m => m.getValue() === 1);Add/Insert member
Members can be added by calling addMember(), addMembers(), insertMember(), or insertMembers():
const member = enumDeclaration.addMember({
name: "newMember",
value: 10,
});Const enum
Check if it's a const enum via isConstEnum():
enumDeclaration.isConstEnum(); // returns: booleanGet the const keyword via getConstKeyword():
enumDeclaration.getConstKeyword(); // returns: Node | undefinedSet if it's a const enum via setIsConstEnum(value):
enumDeclaration.setIsConstEnum(true);
enumDeclaration.setIsConstEnum(false);Enum Members
const member = enumDeclaration.getMember("member");Value
The value can be retrieved whether it is implicitly or explicitly defined:
enumMember.getValue(); // returns: string | numberIt can also be set to a number:
enumMember.setValue(5);Or a string:
enumMember.setValue("string value");Removing
Call remove() on it:
enumMember.remove();2. Official Technical Reference & Guides (dsherret/docs)
GitHub Docs
This repository contains the documentation website code and Markdown source files for docs.github.com.
GitHub's Docs team works on pre-production content in a private repo that regularly syncs with this public repo.
Use the table of contents icon on the top right corner of this document to navigate to a specific section quickly.
Contributing
We accept different types of contributions, including some that don't require you to write a single line of code. For detailed instructions on how to get started with our project, see About contributing to GitHub Docs.
Ways to contribute
On the GitHub Docs site, you can contribute by clicking the Make a contribution button at the bottom of the page to open a pull request for quick fixes like typos, updates, or link fixes.
You can also contribute by creating a local environment or opening a Codespace. For more information, see Setting up your environment to work on GitHub Docs.
For more complex contributions, please open an issue using the most appropriate issue template to describe the changes you'd like to see.
If you're looking for a way to contribute, you can scan through our help wanted board to find open issues already approved for work.
And that's it!
If you're having trouble with your GitHub account, contact Support.
That's how you can easily become a member of the GitHub Docs community. :sparkles:
READMEs
In addition to the README you're reading right now, this repo includes other READMEs that describe the purpose of each subdirectory in more detail:
- content/README.md
- content/graphql/README.md
- content/rest/README.md
- contributing/README.md
- data/README.md
- data/reusables/README.md
- data/variables/README.md
- src/README.md
License
The GitHub product documentation in the assets, content, and data folders are licensed under a CC-BY license.
All other code in this repository is licensed under the MIT license.
When using the GitHub logos, be sure to follow the GitHub logo guidelines.
Thanks :purple_heart:
Thanks for all your contributions and efforts towards improving the GitHub documentation. We thank you for being part of our :sparkles: community :sparkles:!