Typing properties | typescript-transformer | Spatie

 SPATIE

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

spatie.be/open-source

  [Docs](https://spatie.be/docs)  [Typescript-transformer](https://spatie.be/docs/typescript-transformer/v3)  Getting-started  Typing properties

 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)

  Typing properties
- [ 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)

 Typing properties
=================

The first run of TypeScript transformer might not have the desired result, a lot of property types could be `undefined`because TypeScript transformer doesn't know what type these properties are, let's fix that!

Typescript transformer will automatically transform basic PHP types as such:

```
class Types
{
    public string $property; // string
    public int $property; // number
    public float $property; // number
    public bool $property; // boolean
    public mixed $property; // any
    public object $property; // object
}
```

When a type is nullable, TypeScript transformer will transform it as such:

```
class Types
{
    public ?string $property; // string | null
}
```

Unions and intersections are also supported:

```
class Types
{
    public string | int $property; // string | number
    public string & int $property; // string & number
}
```

Arrays in PHP can be transformed to two types in TypeScript, if no types are annotated, an array will become an `Array`. When an array is typed with integer keys it will still be an Array. An array typed with string keys will become a `Record`:

```
class Types
{
    public array $property; // Array

    /** @var bool[] */
    public array $property; // Array

    /** @var array */
    public array $property; // Array

    /** @var array */
    public array $property; // Record
}
```

As you can see, when an array value is typed correctly, it will also be typed correctly in TypeScript.

It is also possible to use non-typical array key types, like an enum:

```
class Types
{
    /** @var array */
    public array $property; // Record
}
```

It is possible to define array shapes like this:

```
class Types
{
    /** @var array{age: int, name: string} */
    public array $property; // { age: number, name: string }
}
```

There are multiple locations where you can add property annotations:

```
/**
* @property string[] $propertyA
 */
class Types
{
    public array $propertyA;

    /** @var string[] */
    public array $propertyB;

    /**
    * @param string[] $propertyC
     */
    public function __construct(
        public array $propertyC
    ) {

    }
}
```

Typing objects works like magic:

```
class Types
{
    // App.Enums.PostType (when using the GlobalNamespaceWriter)
    // Import { PostType } from '../enums' + PostType (when using the ModuleWriter)
    public PostType $property;
}
```

If a typed object is not transformed and thus we don't know how it will look like in TypeScript, it will be replaced by `unknown`. It is possible to replace these unknown types with a TypeScript type, without transforming them, keep reading to learn how to do that.

You can also type generic properties:

```
class Types
{
    /** @var Collection */
    public Collection $property; // Illuminate.Support.Collection
}
```

Properties can be made optional in TypeScript by adding the `#[Optional]` attribute:

```
class Types
{
    #[Optional]
    public string $property;
}
```

Transforming this class will result in the following object:

```
export type Types = {
    property?: string;
}
```

Want to make all properties optional? You can do that by adding the `#[Optional]` attribute to the class:

```
#[Optional]
class Types
{
    public string $property;
}
```

It is possible to hide properties from the TypeScript object by adding the `#[Hidden]` attribute:

```
class Types
{
    #[Hidden]
    public string $property;
}
```

When you want to replace a property type with a literal TypeScript type, you can use the `#[LiteralTypeScriptType]`attribute:

```
class Types
{
    #[LiteralTypeScriptType('Record')]
    public array $property;
}
```

You can also create a TypeScript object from literal types:

```
class Types
{
    #[LiteralTypeScriptType([
        'age' => 'number',
        'name' => 'string',
    ])]
    public array $property;
}
```

This will result in the following TypeScript object:

```
export type Types = {
    property: {
        age: number;
        name: string;
    };
}
```

When your literal type references types from other files, you can add additional imports:

```
use Spatie\TypeScriptTransformer\Attributes\AdditionalImport;

class Types
{
    #[LiteralTypeScriptType(
        'Record',
        additionalImports: [
            new AdditionalImport(__DIR__.'/../types/components.ts', 'SomeComponent'),
        ]
    )]
    public array $property;
}
```

This generates the correct import statement and resolves the name, including aliasing when there are conflicts. You can import multiple names from the same file:

```
new AdditionalImport(__DIR__.'/../types/components.ts', ['SomeComponent', 'OtherThing'])
```

### Referencing other transformed types

When your literal type needs to reference other PHP types that are also being transformed, use the `references` parameter with `%placeholder%` syntax:

```
use Spatie\TypeScriptTransformer\Attributes\LiteralTypeScriptType;

class Types
{
    #[LiteralTypeScriptType(
        'Record | %Post%[]',
        references: [
            'User' => UserData::class,
            'Post' => PostData::class,
        ]
    )]
    public array $property;
}
```

Each placeholder `%Name%` in the TypeScript string will be replaced with the resolved type name. This integrates into the full reference graph — imports are generated in module mode, aliases are resolved when there are naming conflicts, and missing references are tracked.

You can also pass custom `Reference` objects:

```
use Spatie\TypeScriptTransformer\References\CustomReference;

#[LiteralTypeScriptType(
    '%Custom% | null',
    references: [
        'Custom' => new CustomReference('group', 'name'),
    ]
)]
```

It is also possible to type properties using php types within an attribute using the `#[TypeScriptType]` attribute:

```
class Types
{
    #[TypeScriptType('string')]
    public $property;
}
```

This attribute also can be used to type an object, but this time the types can be PHP types:

```
class Types
{
    #[TypeScriptType([
        'age' => 'int',
        'name' => 'string',
    ])]
    public $property;
}
```

 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)
