Visiting TypeScript nodes | typescript-transformer | Spatie

 SPATIE

  TypeScript Transformer
=========================

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Typescript-transformer](https://spatie.be/docs/typescript-transformer/v3)  Typescript-nodes  Visiting TypeScript nodes

 Version   v3   v2   v1

 Other versions for crawler [v3](https://spatie.be/docs/typescript-transformer/v3) [v2](https://spatie.be/docs/typescript-transformer/v2) [v1](https://spatie.be/docs/typescript-transformer/v1)

  Visiting TypeScript nodes
- [ Introduction ](https://spatie.be/docs/typescript-transformer/v3/introduction)
- [ Postcardware ](https://spatie.be/docs/typescript-transformer/v3/postcardware)
- [ Installation ](https://spatie.be/docs/typescript-transformer/v3/installation)
- [ Questions &amp; issues ](https://spatie.be/docs/typescript-transformer/v3/questions-and-issues)
- [ Changelog ](https://spatie.be/docs/typescript-transformer/v3/changelog)
- [ About us ](https://spatie.be/docs/typescript-transformer/v3/about-us)

Getting started
---------------

- [ Setting up ](https://spatie.be/docs/typescript-transformer/v3/getting-started/setting-up)
- [ Running TypeScript Transformer for the first time ](https://spatie.be/docs/typescript-transformer/v3/getting-started/first-run)
- [ Special attributes ](https://spatie.be/docs/typescript-transformer/v3/getting-started/attributes)
- [ Typing properties ](https://spatie.be/docs/typescript-transformer/v3/getting-started/typing-properties)
- [ Replacing common types ](https://spatie.be/docs/typescript-transformer/v3/getting-started/replacing-types)
- [ Formatters ](https://spatie.be/docs/typescript-transformer/v3/getting-started/formatters)

Laravel
-------

- [ Installation and setup ](https://spatie.be/docs/typescript-transformer/v3/laravel/installation-and-setup)
- [ Laravel Data ](https://spatie.be/docs/typescript-transformer/v3/laravel/laravel-data)
- [ Controllers ](https://spatie.be/docs/typescript-transformer/v3/laravel/controllers)
- [ Routes ](https://spatie.be/docs/typescript-transformer/v3/laravel/routes)
- [ Route filters ](https://spatie.be/docs/typescript-transformer/v3/laravel/route-filters)
- [ Watch mode ](https://spatie.be/docs/typescript-transformer/v3/laravel/watch-mode)

Custom transformers
-------------------

- [ Getting started ](https://spatie.be/docs/typescript-transformer/v3/transformers/getting-started)
- [ Class transformer ](https://spatie.be/docs/typescript-transformer/v3/transformers/class-transformer)
- [ Enum transformer ](https://spatie.be/docs/typescript-transformer/v3/transformers/enum-transformer)

Transformed providers
---------------------

- [ Getting started ](https://spatie.be/docs/typescript-transformer/v3/providers/getting-started)
- [ Using different writers in providers ](https://spatie.be/docs/typescript-transformer/v3/providers/writers-in-providers)
- [ Logging in providers ](https://spatie.be/docs/typescript-transformer/v3/providers/logging)
- [ Referencing types ](https://spatie.be/docs/typescript-transformer/v3/providers/references)
- [ Helpers ](https://spatie.be/docs/typescript-transformer/v3/providers/helpers)

TypeScript nodes
----------------

- [ Introduction ](https://spatie.be/docs/typescript-transformer/v3/typescript-nodes/introduction)
- [ Building your own TypeScript node ](https://spatie.be/docs/typescript-transformer/v3/typescript-nodes/custom-nodes)
- [ Visiting TypeScript nodes ](https://spatie.be/docs/typescript-transformer/v3/typescript-nodes/visitor)
- [ Node reference ](https://spatie.be/docs/typescript-transformer/v3/typescript-nodes/reference)

Watch mode
----------

- [ How does it work? ](https://spatie.be/docs/typescript-transformer/v3/watch-mode/how-it-works)
- [ Setting up the runner ](https://spatie.be/docs/typescript-transformer/v3/watch-mode/setting-up-the-runner)
- [ Watch events ](https://spatie.be/docs/typescript-transformer/v3/watch-mode/watch-events)
- [ PHP Nodes ](https://spatie.be/docs/typescript-transformer/v3/watch-mode/php-nodes)

Advanced
--------

- [ Extensions ](https://spatie.be/docs/typescript-transformer/v3/advanced/extensions)
- [ Managing transformers ](https://spatie.be/docs/typescript-transformer/v3/advanced/managing-transformers)
- [ Loggers ](https://spatie.be/docs/typescript-transformer/v3/advanced/loggers)
- [ Custom writers ](https://spatie.be/docs/typescript-transformer/v3/advanced/custom-writers)

 Visiting TypeScript nodes
=========================

###  On this page

1. [ Hooking into TypeScript transformer ](#content-hooking-into-typescript-transformer)

When working with TypeScript nodes in a class property processor or a custom TypeScript node, it might be necessary to visit and alter nodes in the tree. The `Visitor` class can be used to visit such a tree of TypeScript nodes.

The visitor will start in a node and then traverse the tree of TypeScript nodes, it is possible to register a `before`and `after` callback for each node it visits. The `before` callback is called before visiting the children of a node and the `after` callback is called after visiting the children of a node.

```
use Spatie\TypeScriptTransformer\Visitor\Visitor;

Visitor::create()
    ->before(function (TypeScriptNode $node){
        echo 'Before visiting ' . $node::class . PHP_EOL;
    })
    ->after(function (TypeScriptNode $node) {
        echo 'After visiting ' . $node::class . PHP_EOL;
    })
    ->execute($rootNode);
```

When running the visitor on the following node:

```
$rootNode = new TypeScriptUnion([
    new TypeScriptString(),
    new TypeScriptNumber(),
]);
```

The output will be (redacted for readability):

```
Before visiting TypeScriptUnion
Before visiting TypeScriptString
After visiting TypeScriptString
Before visiting TypeScriptNumber
After visiting TypeScriptNumber
After visiting TypeScriptUnion
```

By default, the visitor will visit the tree of nodes and run the callback on each node within the tree. It is possible to limit the types of nodes the callback runs on:

```
Visitor::create()
    ->after(function (TypeScriptUnion $node, [TypeScriptUnion::class]) {
        // Do something with TypeScriptUnion nodes
    })
    ->execute($rootNode);
```

When not returning a TypeScript node from the callback, the visitor will continue traversing the tree. It is possible to replace a node in the tree like this:

```
use Spatie\TypeScriptTransformer\Visitor\VisitorOperation;

Visitor::create()
    ->after(function (TypeScriptUnion $node, [TypeScriptUnion::class]) {
        if(count($node->types) === 1) {
            return VisitorOperation::replace(array_values($node->types)[0]);
        }
    })
    ->execute($rootNode);
```

The visitor above will replace all union nodes with a single type with that type.

It is also possible to remove a node from the tree:

```
Visitor::create()
    ->after(function (TypeScriptString $node, [TypeScriptString::class]) {
        return VisitorOperation::remove();
    })
    ->execute($rootNode);
```

Hooking into TypeScript transformer
-----------------------------------------------------------------------------------------------------------------------------------------------------------------

Every time the TypeScript transformer is executed, it will go through a series of steps, it is possible to run a visitor in between some of these steps.

The steps look as following:

1. Running of the TransformedProviders creating a collection of Transformed objects
2. Running other providers to add extra Transformed objects
3. Possible hooking point: `providedVisitorHook`
4. Connecting references between Transformed objects
5. Possible hooking point: `connectedVisitorHook`
6. Create a collection of WriteableFiles
7. Write those files to disk
8. Format the files

The two hooking points below can be used to run a visitor on the collection of Transformed objects:

```
use Spatie\TypeScriptTransformer\Visitor\VisitorClosureType;

$config->providedVisitorHook(
    fn(TransformedCollection $collection) => Visitor::create()->execute($collection),
    [TypeScriptUnion::class],
    VisitorClosureType::Before
);

$config->connectedVisitorHook(
    fn(TransformedCollection $collection) => Visitor::create()->execute($collection),
    [TypeScriptUnion::class],
    VisitorClosureType::Before
);
```

Running visitors as an after hook is also possible:

```
$config->providedVisitorHook(
    fn(TransformedCollection $collection) => Visitor::create()->execute($collection),
    [TypeScriptUnion::class],
    VisitorClosureType::After
);

$config->connectedVisitorHook(
    fn(TransformedCollection $collection) => Visitor::create()->execute($collection),
    [TypeScriptUnion::class],
    VisitorClosureType::After
);
```

 A good
match?
-------------

### What we do best

- All things Laravel
- Custom frontend components
- Building APIs
- AI-powered features
- Simplifying things
- Clean solutions
- Integrating services

### Not our cup of tea

- WordPress themes
- Cutting corners
- Free mockups to win a job
- "Just execute the briefing"

 In short: we'd like to be a **substantial part** of your project.

 [ Get in touch via email ](mailto:info@spatie.be?subject=A%20good%20match%21&body=Tell%20us%20as%20much%20as%20you%20can%20about%0A-%20your%20online%20project%0A-%20your%20planning%0A-%20your%20budget%0A-%20%E2%80%A6%0A%0AAnything%20that%20helps%20us%20to%20start%20straightforward%21)
