Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Typescript Transformer Laravel Package

spatie/typescript-transformer

Automatically generate TypeScript definitions from your PHP/Laravel code. spatie/typescript-transformer scans classes and types, then outputs .d.ts files so your frontend stays in sync with backend models, DTOs and enums with minimal manual typing.

View on GitHub
Deep Wiki
Context7

title: Typing properties weight: 4

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](https://github.com/var) bool[] */
    public array $property; // Array<boolean>

    /** [@var](https://github.com/var) array<int, bool> */
    public array $property; // Array<boolean>

    /** [@var](https://github.com/var) array<string, bool> */
    public array $property; // Record<string, boolean>
}

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](https://github.com/var) array<PostType, string> */
    public array $property; // Record<'news'|'blog', string>
}

It is possible to define array shapes like this:

class Types
{
    /** [@var](https://github.com/var) array{age: int, name: string} */
    public array $property; // { age: number, name: string }
}

There are multiple locations where you can add property annotations:

/**
* [@property](https://github.com/property) string[] $propertyA
 */
class Types
{
    public array $propertyA;

    /** [@var](https://github.com/var) string[] */
    public array $propertyB;

    /**
    * [@param](https://github.com/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](https://github.com/var) Collection<int, string> */
    public Collection $property; // Illuminate.Support.Collection<number, string>
}

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<Uppercase<string>, string>')]
    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<string, SomeComponent>',
        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<string, %User%> | %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;
}
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor