PHPackages                             campelo/laravel-typescript-models - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. campelo/laravel-typescript-models

ActiveLibrary[Database &amp; ORM](/categories/database)

campelo/laravel-typescript-models
=================================

Automatically generate TypeScript interfaces from your Laravel Eloquent models via API endpoint

v1.7.0(3mo ago)08MITPHPPHP ^8.1

Since Feb 12Pushed 3mo agoCompare

[ Source](https://github.com/campeloneto1/laravel-typescript-models)[ Packagist](https://packagist.org/packages/campelo/laravel-typescript-models)[ Docs](https://github.com/campelo/laravel-typescript-models)[ RSS](/packages/campelo-laravel-typescript-models/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (5)Versions (10)Used By (0)

Laravel TypeScript Models
=========================

[](#laravel-typescript-models)

Automatically generate TypeScript interfaces from your Laravel Eloquent models, API Resources, and Form Requests via an API endpoint or CLI command.

Features
--------

[](#features)

- **API Resources (Recommended)**: Generate interfaces from JsonResource classes as source of truth
- **Models**: Generate TypeScript interfaces from Eloquent models (opt-in)
- **Form Requests**: Generate interfaces from FormRequest validation rules
- **Yup Schemas**: Generate Yup validation schemas from Form Requests
- **Zod Schemas**: Generate Zod validation schemas from Form Requests
- **Intelligent Type Inference**: Eliminate `any` types using PHPDoc, static analysis, and Model casts
- **Split by Domain**: Generate separate files per module (`users.ts`, `orders.ts`)
- **Union Literal Types**: Enum-like types from `in:` rules (`'admin' | 'user' | 'guest'`)
- **Pagination Types**: Auto-generated `PaginatedResponse` generic type
- **Array Types**: Auto-generated array types (`Users`, `Posts`, etc.)
- **Smart Detection**: Multiple strategies for type detection (return type, PHPDoc, method body)
- **Conflict Resolution**: Automatic name prefixing when classes have the same name in different folders
- **CLI Command**: `php artisan typescript:generate` for CI/CD integration
- **Web Configurator**: Interactive HTML page to customize and download types
- **Security**: Token authentication, IP whitelist, disabled by default

Installation
------------

[](#installation)

```
composer require campelo/laravel-typescript-models
```

The package will automatically register its service provider.

Configuration
-------------

[](#configuration)

Publish the configuration file:

```
php artisan vendor:publish --tag=typescript-models-config
```

### Environment Variables

[](#environment-variables)

```
# Enable the endpoint (disable in production!)
TYPESCRIPT_MODELS_ENABLED=true

# Secret token for authentication
TYPESCRIPT_MODELS_TOKEN=your-secret-token-here

# Optional: Custom route path
TYPESCRIPT_MODELS_ROUTE=/api/typescript-models

# Optional: Allowed IPs (comma-separated)
TYPESCRIPT_MODELS_ALLOWED_IPS=127.0.0.1,::1

# Optional: Properties mode (fillable, database, or both)
TYPESCRIPT_MODELS_PROPERTIES_MODE=fillable

# Optional: Include/exclude features
TYPESCRIPT_MODELS_INCLUDE_MODELS=false           # Models disabled by default (use Resources!)
TYPESCRIPT_MODELS_INCLUDE_ACCESSORS=false
TYPESCRIPT_MODELS_INCLUDE_RELATIONS=true
TYPESCRIPT_MODELS_INCLUDE_RESOURCES=true
TYPESCRIPT_MODELS_INCLUDE_REQUESTS=true
TYPESCRIPT_MODELS_GENERATE_YUP_SCHEMAS=true
TYPESCRIPT_MODELS_GENERATE_ZOD_SCHEMAS=false

# Type inference for Resources (eliminates 'any' types)
TYPESCRIPT_MODELS_INFER_TYPES=true
TYPESCRIPT_MODELS_UNKNOWN_FALLBACK=unknown       # 'unknown' | 'any' | 'never'

# Split output by domain
TYPESCRIPT_MODELS_SPLIT_BY_DOMAIN=false          # 'subdirectory' | 'class' | false
TYPESCRIPT_MODELS_DOMAIN_DETECTION=subdirectory
```

Usage
-----

[](#usage)

### CLI Command (Recommended)

[](#cli-command-recommended)

Generate TypeScript interfaces directly from the command line:

```
# Generate with default options (Resources + Requests, no Models)
php artisan typescript:generate

# Specify output file
php artisan typescript:generate --output=resources/js/types/api.d.ts

# Control what to generate with --only and --include
php artisan typescript:generate --only=resources              # Only resources
php artisan typescript:generate --only=resources,requests     # Resources + Requests
php artisan typescript:generate --include=models              # Add models to default

# Legacy flags (still supported)
php artisan typescript:generate --models          # Only models
php artisan typescript:generate --resources       # Only resources
php artisan typescript:generate --requests        # Only requests

# Choose validation schema library
php artisan typescript:generate --yup            # Generate Yup schemas
php artisan typescript:generate --zod            # Generate Zod schemas
php artisan typescript:generate --yup --zod      # Generate both

# Split by domain (generates multiple files)
php artisan typescript:generate --split-by=subdirectory --output=resources/types/
# Creates: users.ts, orders.ts, _shared.ts, index.ts

# Exclude pagination/array types
php artisan typescript:generate --no-paginated --no-array-types
```

### Web Configurator

[](#web-configurator)

Access the interactive configurator page to customize and download your types:

```
http://localhost/api/typescript-models/configurator?token=your-secret-token

```

Features:

- Toggle models, resources, requests
- Enable/disable relations and accessors
- Choose between Yup and Zod schemas
- Preview before download
- Copy generated URL for CI/CD

### API Endpoint

[](#api-endpoint)

```
# Using token in header
curl -H "X-TypeScript-Token: your-secret-token" http://localhost/api/typescript-models

# Using Bearer token
curl -H "Authorization: Bearer your-secret-token" http://localhost/api/typescript-models

# Using query parameter
curl "http://localhost/api/typescript-models?token=your-secret-token"

# With custom options
curl "http://localhost/api/typescript-models?token=your-token&resources=1&requests=1&yup=1&zod=0"
```

### Integrating with Your Frontend

[](#integrating-with-your-frontend)

```
// package.json
{
  "scripts": {
    "types:generate": "curl -H 'X-TypeScript-Token: your-token' http://localhost/api/typescript-models > src/types/models.d.ts"
  }
}
```

---

Resources vs Models: Best Practices
-----------------------------------

[](#resources-vs-models-best-practices)

**Resources are the recommended source of truth** for frontend types because:

- They represent the actual API response shape
- They hide internal fields that shouldn't be exposed
- Multiple Resources can exist for the same Model (summary, detail, admin)

By default, **Models are disabled** (`include_models=false`). Enable them only if needed:

```
# Default: Only Resources + Requests
php artisan typescript:generate

# Include Models for admin panels or internal tools
php artisan typescript:generate --include=models

# Or via config
TYPESCRIPT_MODELS_INCLUDE_MODELS=true
```

---

Split by Domain
---------------

[](#split-by-domain)

For large codebases, split generated types into separate files:

```
php artisan typescript:generate --split-by=subdirectory --output=resources/types/
```

### Directory Structure

[](#directory-structure)

Given this Resource structure:

```
app/Http/Resources/
├── Users/
│   ├── UserResource.php
│   └── UserSummaryResource.php
├── Orders/
│   └── OrderResource.php
└── ProductResource.php  (no subdirectory)

```

Generates:

```
resources/types/
├── _shared.ts     # PaginatedResponse, PaginationLink
├── index.ts       # Re-exports everything
├── users.ts       # UserResource, UserSummaryResource
├── orders.ts      # OrderResource
└── default.ts     # ProductResource (no subdirectory)

```

### Generated Files

[](#generated-files)

**\_shared.ts**

```
export interface PaginatedResponse { ... }
export interface PaginationLink { ... }
```

**users.ts**

```
import type { PaginatedResponse } from './_shared';

export interface UserResource { ... }
export interface UserSummaryResource { ... }
export type UserResources = UserResource[];
export type UserResourcesPaginated = PaginatedResponse;
```

**index.ts**

```
export * from './_shared';
export * from './users';
export * from './orders';
export * from './default';
```

### Detection Modes

[](#detection-modes)

ModeDescriptionExample`subdirectory`Uses namespace subdirectory`Resources\Users\` → `users.ts``class`Groups by matching Model names`UserResource`, `StoreUserRequest` → `user.ts`### Class Mode (Entity Matching)

[](#class-mode-entity-matching)

The `class` mode intelligently groups interfaces by matching against your discovered Models:

```
php artisan typescript:generate --split-by=class --output=resources/types/
```

**How it works:**

1. Discovers all your Eloquent Models (`User`, `Post`, `PostLike`, etc.)
2. For each Resource/Request, removes suffixes (`Resource`, `Request`) and HTTP verb prefixes (`Store`, `Update`, `Delete`, `Index`, `Show`, `Create`, `Destroy`)
3. Matches the clean name against Model names (exact match or plural match)

**Examples:**

ClassClean NameMatched ModelOutput File`UserResource``User``User``user.ts``StoreUserRequest``User``User``user.ts``DeletePostLikeRequest``PostLike``PostLike``post_like.ts``PostLikesResource``PostLikes``PostLike` (plural)`post_like.ts``TripUserResource``TripUser``TripUser``trip_user.ts`> **Note:** The matching is exact to avoid conflicts. For example, with Models `User`, `Trip`, and `TripUser`, the class `TripUserRequest` will correctly match `TripUser` (not `User` or `Trip`).

---

1. Model Interfaces
-------------------

[](#1-model-interfaces)

Generate TypeScript interfaces from your Eloquent models.

### Laravel Model

[](#laravel-model)

```
// app/Models/User.php
class User extends Model
{
    protected $fillable = ['name', 'email', 'birth_date'];

    protected $casts = [
        'birth_date' => 'date',
    ];

    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }

    public function profile(): HasOne
    {
        return $this->hasOne(Profile::class);
    }
}
```

### Generated TypeScript

[](#generated-typescript)

```
// Model Interfaces
export interface User {
  id: number;
  name?: string;
  email?: string;
  birth_date?: Date;
  created_at?: Date;
  updated_at?: Date;
  posts?: Post[];
  profile?: Profile;
}

export interface Post {
  id: number;
  title?: string;
  content?: string;
  user_id?: number;
  created_at?: Date;
  updated_at?: Date;
  user?: User;
}

// Model Array Types
export type Users = User[];
export type Posts = Post[];

// Model Paginated Types
export type UsersPaginated = PaginatedResponse;
export type PostsPaginated = PaginatedResponse;
```

### Relationship Detection

[](#relationship-detection)

The package uses **3 strategies** to detect relationships:

1. **Return Type (Recommended)**

```
public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}
```

2. **PHPDoc Annotation**

```
/** @return HasMany */
public function posts()
{
    return $this->hasMany(Post::class);
}
```

3. **Method Body Analysis**

```
public function posts()
{
    return $this->hasMany(Post::class); // Auto-detected!
}
```

### Supported Relationships

[](#supported-relationships)

RelationshipTypeScript Type`HasOne`, `BelongsTo`, `MorphOne`, `MorphTo`, `HasOneThrough``RelatedModel``HasMany`, `BelongsToMany`, `MorphMany`, `MorphToMany`, `HasManyThrough``RelatedModel[]`---

2. API Resource Interfaces
--------------------------

[](#2-api-resource-interfaces)

Generate interfaces from your API Resources. Useful when your API response differs from the model structure.

### Laravel Resources

[](#laravel-resources)

```
// app/Http/Resources/UserResource.php
class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'full_name' => $this->name,
            'email' => $this->email,
            'avatar_url' => $this->getAvatarUrl(),
            'member_since' => $this->created_at->format('Y-m-d'),
        ];
    }
}

// app/Http/Resources/UserSummaryResource.php
class UserSummaryResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
        ];
    }
}

// app/Http/Resources/UserProfileResource.php
class UserProfileResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'full_name' => $this->name,
            'email' => $this->email,
            'bio' => $this->profile->bio,
            'posts_count' => $this->posts->count(),
        ];
    }
}
```

### Generated TypeScript (with Intelligent Type Inference)

[](#generated-typescript-with-intelligent-type-inference)

```
// Resource Interfaces - No more 'any' types!
export interface UserResource {
  avatar_url?: string;        // Inferred from name pattern (*_url)
  email?: string;             // Inferred from name pattern
  full_name?: string;         // Inferred from name pattern
  id?: number;                // Inferred from name pattern
  member_since?: string;      // Inferred from ->format() call
}

export interface UserSummaryResource {
  id?: number;
  name?: string;
}

export interface UserProfileResource {
  bio?: string;
  email?: string;
  full_name?: string;
  id?: number;
  posts_count?: number;       // Inferred from name pattern (*_count)
}

// Resource Array Types
export type UserResources = UserResource[];
export type UserSummaryResources = UserSummaryResource[];
export type UserProfileResources = UserProfileResource[];

// Resource Paginated Types
export type UserResourcesPaginated = PaginatedResponse;
export type UserSummaryResourcesPaginated = PaginatedResponse;
export type UserProfileResourcesPaginated = PaginatedResponse;
```

### PHPDoc Type Hints (Recommended)

[](#phpdoc-type-hints-recommended)

For full control over types, use PHPDoc annotations:

```
/**
 * @property int $id
 * @property string $full_name
 * @property string $email
 * @property string $avatar_url
 * @property PostResource[] $posts
 */
class UserResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'full_name' => $this->name,
            'email' => $this->email,
            'avatar_url' => $this->getAvatarUrl(),
            'posts' => PostResource::collection($this->posts),
        ];
    }
}
```

### How Type Inference Works

[](#how-type-inference-works)

The package uses **multiple strategies** to determine types (in priority order):

1. **PHPDoc `@property`**: Highest priority, most reliable
2. **Static Analysis**: Detects patterns in `toArray()`:
    - `PostResource::collection(...)` → `PostResource[]`
    - `new UserResource(...)` → `UserResource`
    - `(bool) $value` → `boolean`
    - `->format('Y-m-d')` → `string`
3. **Model Casts**: Inherits types from the underlying Model
4. **Name Patterns**:
    - `*_id`, `id` → `number`
    - `*_at`, `*_date` → `string`
    - `is_*`, `has_*`, `can_*` → `boolean`
    - `*_count` → `number`
    - `*_url`, `email`, `name` → `string`
5. **Fallback**: `unknown` (configurable via `unknown_type_fallback`)

---

3. Form Request Interfaces
--------------------------

[](#3-form-request-interfaces)

Generate interfaces from your Form Request validation rules. Perfect for typing your frontend forms.

### Laravel Form Requests

[](#laravel-form-requests)

```
// app/Http/Requests/StoreUserRequest.php
class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
            'password' => 'required|string|min:8|confirmed',
            'age' => 'nullable|integer|min:18',
            'roles' => 'required|array',
            'roles.*' => 'exists:roles,id',
            'avatar' => 'nullable|image|max:2048',
        ];
    }
}

// app/Http/Requests/UpdateUserRequest.php
class UpdateUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'sometimes|string|max:255',
            'email' => 'sometimes|email',
            'bio' => 'nullable|string|max:1000',
        ];
    }
}
```

### Generated TypeScript

[](#generated-typescript-1)

```
// Form Request Interfaces
export interface StoreUserRequest {
  age?: number;
  avatar?: File;
  email: string;
  name: string;
  password: string;
  roles: any[];
}

export interface UpdateUserRequest {
  bio?: string;
  email?: string;
  name?: string;
}
```

### Type Mapping from Validation Rules

[](#type-mapping-from-validation-rules)

Laravel RuleTypeScript Type`integer`, `numeric``number``boolean`, `accepted``boolean``array``any[]``file`, `image`, `mimes``File``json``Record``string`, `email`, `url`, `uuid`, `date``string``required`Required field (no `?`)`nullable`, `sometimes`Optional field (`?`)### Conflict Resolution

[](#conflict-resolution)

When you have requests with the same name in different folders, the package automatically adds a prefix:

```
app/Http/Requests/
├── StoreUserRequest.php         → StoreUserRequest
├── UpdateUserRequest.php        → UpdateUserRequest
└── Admin/
    └── StoreUserRequest.php     → AdminStoreUserRequest
    └── Api/
        └── V1/
            └── StoreUserRequest.php → AdminApiV1StoreUserRequest

```

---

4. Yup Validation Schemas
-------------------------

[](#4-yup-validation-schemas)

Generate Yup schemas from your Form Requests for client-side validation.

### Laravel Form Request

[](#laravel-form-request)

```
class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'required|string|min:2|max:255',
            'email' => 'required|email',
            'password' => 'required|string|min:8|confirmed',
            'age' => 'nullable|integer|min:18|max:120',
            'website' => 'nullable|url',
            'role' => 'required|in:admin,user,guest',
        ];
    }
}
```

### Generated Yup Schema

[](#generated-yup-schema)

```
// Yup Validation Schemas
// Usage: import * as yup from 'yup';

export const StoreUserRequestSchema = yup.object({
  name: yup.string().required('This field is required').min(2, 'Must be at least 2 characters').max(255, 'Must be at most 255 characters'),
  email: yup.string().required('This field is required').email('Invalid email address'),
  password: yup.string().required('This field is required').min(8, 'Must be at least 8 characters').oneOf([yup.ref('password_confirmation')], 'Must match confirmation'),
  age: yup.number().nullable().min(18, 'Must be at least 18').max(120, 'Must be at most 120'),
  website: yup.string().nullable().url('Invalid URL'),
  role: yup.string().required('This field is required').oneOf(['admin', 'user', 'guest'], 'Invalid value'),
});
```

### Using in React/Vue

[](#using-in-reactvue)

```
// React example with react-hook-form
import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { StoreUserRequest, StoreUserRequestSchema } from '@/types/models';

function UserForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: yupResolver(StoreUserRequestSchema)
  });

  const onSubmit = (data: StoreUserRequest) => {
    // data is typed!
    api.post('/users', data);
  };

  return (

      {errors.name && {errors.name.message}}
      {/* ... */}

  );
}
```

### Supported Yup Validations

[](#supported-yup-validations)

Laravel RuleYup Method`required``.required()``nullable``.nullable()``email``.email()``url``.url()``uuid``.uuid()``min:n``.min(n)``max:n``.max(n)``between:a,b``.min(a).max(b)``size:n``.length(n)``in:a,b,c``.oneOf(['a','b','c'])``confirmed``.oneOf([yup.ref('field_confirmation')])``integer``.integer()``regex``.matches()`---

5. Zod Validation Schemas
-------------------------

[](#5-zod-validation-schemas)

Generate Zod schemas from your Form Requests. Zod is a TypeScript-first schema validation library.

### Enable Zod Schemas

[](#enable-zod-schemas)

```
TYPESCRIPT_MODELS_GENERATE_ZOD_SCHEMAS=true
```

### Laravel Form Request

[](#laravel-form-request-1)

```
class StoreUserRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'name' => 'required|string|min:2|max:255',
            'email' => 'required|email',
            'role' => 'required|in:admin,user,guest',
            'age' => 'nullable|integer|min:18',
        ];
    }
}
```

### Generated Zod Schema

[](#generated-zod-schema)

```
// Zod Validation Schemas
// Usage: import { z } from 'zod';

export const StoreUserRequestSchema = z.object({
  name: z.string().min(2, { message: 'Must be at least 2 characters' }).max(255, { message: 'Must be at most 255 characters' }),
  email: z.string().email({ message: 'Invalid email address' }),
  role: z.enum(['admin', 'user', 'guest']),
  age: z.number().min(18, { message: 'Must be at least 18' }).nullable().optional(),
});
```

### Using in React

[](#using-in-react)

```
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { StoreUserRequestSchema } from '@/types/models';

type StoreUserRequest = z.infer;

function UserForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(StoreUserRequestSchema)
  });

  // ...
}
```

---

6. Enum Union Literal Types
---------------------------

[](#6-enum-union-literal-types)

The package automatically generates TypeScript union literal types from `in:` validation rules and `Rule::in()`:

### Laravel Validation

[](#laravel-validation)

```
// Using string rule
'role' => 'required|in:admin,user,guest',

// Using Rule::in()
'status' => ['required', Rule::in(['pending', 'approved', 'rejected'])],

// Using Enum rule (Laravel 9+)
'type' => ['required', Rule::enum(OrderType::class)],
```

### Generated TypeScript

[](#generated-typescript-2)

```
export interface StoreOrderRequest {
  role: 'admin' | 'user' | 'guest';
  status: 'pending' | 'approved' | 'rejected';
  type: 'delivery' | 'pickup' | 'dine_in';
}
```

This provides much stronger typing than generic `string` types!

---

7. Pagination Types
-------------------

[](#7-pagination-types)

Auto-generated generic pagination interfaces:

```
export interface PaginationLink {
  url: string | null;
  label: string;
  active: boolean;
}

export interface PaginatedResponse {
  data: T[];
  current_page: number;
  first_page_url: string;
  from: number | null;
  last_page: number;
  last_page_url: string;
  links: PaginationLink[];
  next_page_url: string | null;
  path: string;
  per_page: number;
  prev_page_url: string | null;
  to: number | null;
  total: number;
}
```

### Usage

[](#usage-1)

```
// Fetch paginated users
const response = await api.get('/users');

console.log(response.data);        // User[]
console.log(response.total);       // number
console.log(response.current_page); // number
```

---

Configuration Options
---------------------

[](#configuration-options)

### Models

[](#models)

```
'include_models' => false, // Disabled by default (use Resources!)

'models_paths' => [
    app_path('Models'),
],

'exclude_models' => [
    // App\Models\SomeModel::class,
],

'properties_mode' => 'fillable', // fillable, database, or both

'include_accessors' => false,

'include_relations' => true,
```

### Resources

[](#resources)

```
'include_resources' => true,

'resources_paths' => [
    app_path('Http/Resources'),
],

'exclude_resources' => [
    // App\Http\Resources\SomeResource::class,
],

// Type inference to eliminate 'any' types
'infer_resource_types' => true,

// What to use when type cannot be inferred
'unknown_type_fallback' => 'unknown', // 'unknown' | 'any' | 'never'
```

### Form Requests

[](#form-requests)

```
'include_requests' => true,

'requests_paths' => [
    app_path('Http/Requests'),
],

'exclude_requests' => [
    // App\Http\Requests\SomeRequest::class,
],

'generate_yup_schemas' => true,
'generate_zod_schemas' => false,
```

### Split by Domain

[](#split-by-domain-1)

```
// Split output into multiple files
'split_by_domain' => false, // 'subdirectory' | 'class' | false

// How to detect domain from class namespace
'domain_detection' => 'subdirectory', // 'subdirectory' | 'class_basename'
```

---

Complete Output Example
-----------------------

[](#complete-output-example)

```
// =============================================================================
// Auto-generated TypeScript interfaces from Laravel Models
// Generated at: 2024-01-15T10:30:00+00:00
// Do not edit this file manually - it will be overwritten
// =============================================================================

// Pagination Interfaces
export interface PaginationLink {
  url: string | null;
  label: string;
  active: boolean;
}

export interface PaginatedResponse {
  data: T[];
  current_page: number;
  // ... other pagination fields
}

// Resource Interfaces (with intelligent type inference - no 'any'!)
export interface UserResource {
  id?: number;
  full_name?: string;
  avatar_url?: string;
  posts?: PostResource[];
}

export interface UserSummaryResource {
  id?: number;
  name?: string;
}

// Resource Array Types
export type UserResources = UserResource[];
export type UserSummaryResources = UserSummaryResource[];

// Resource Paginated Types
export type UserResourcesPaginated = PaginatedResponse;
export type UserSummaryResourcesPaginated = PaginatedResponse;

// Form Request Interfaces
export interface StoreUserRequest {
  email: string;
  name: string;
  password: string;
  age?: number;
}

export interface UpdateUserRequest {
  email?: string;
  name?: string;
}

// Yup Validation Schemas
// Usage: import * as yup from 'yup';
export const StoreUserRequestSchema = yup.object({
  email: yup.string().required('This field is required').email('Invalid email address'),
  name: yup.string().required('This field is required').max(255, 'Must be at most 255 characters'),
  password: yup.string().required('This field is required').min(8, 'Must be at least 8 characters'),
  age: yup.number().nullable().min(18, 'Must be at least 18'),
});

export const UpdateUserRequestSchema = yup.object({
  email: yup.string().optional().email('Invalid email address'),
  name: yup.string().optional().max(255, 'Must be at most 255 characters'),
});
```

---

Security Recommendations
------------------------

[](#security-recommendations)

1. **Never enable in production** - Set `TYPESCRIPT_MODELS_ENABLED=false`
2. **Use strong tokens** - Generate a secure random token
3. **Restrict IPs** - Limit to localhost or known development IPs
4. **Use HTTPS** - Always use HTTPS when transmitting tokens
5. **Exclude sensitive models** - Don't expose internal/admin models

---

Type Mapping Reference
----------------------

[](#type-mapping-reference)

### PHP/Laravel to TypeScript

[](#phplaravel-to-typescript)

PHP/Laravel TypeTypeScript Type`int`, `integer``number``float`, `double`, `decimal``number``bool`, `boolean``boolean``array`, `json`, `collection``any[]``object``Record``datetime`, `date`, `timestamp``Date``string` (default)`string`### Validation Rules to TypeScript

[](#validation-rules-to-typescript)

Laravel RuleTypeScript Type`integer`, `numeric``number``boolean`, `accepted``boolean``array``any[]``file`, `image``File``json``Record`Other`string`---

License
-------

[](#license)

MIT License - see [LICENSE](LICENSE) file.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance82

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

8

Last Release

94d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9f3acde28c4144b8432fbcd2fbaeaeb877c63519b556724f7f4d920842a9eb81?d=identicon)[campeloneto1](/maintainers/campeloneto1)

---

Tags

interfaceslaraveleloquenttypescriptmodelscode-generation

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/campelo-laravel-typescript-models/health.svg)

```
[![Health](https://phpackages.com/badges/campelo-laravel-typescript-models/health.svg)](https://phpackages.com/packages/campelo-laravel-typescript-models)
```

###  Alternatives

[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[laravel/wayfinder

Generate TypeScript representations of your Laravel actions and routes.

1.7k4.1M69](/packages/laravel-wayfinder)[toponepercent/baum

Baum is an implementation of the Nested Set pattern for Eloquent models.

3154.7k](/packages/toponepercent-baum)[pursehouse/modeler-laravel-eloquent

Generate model classes for Eloquent in Laravel

112.4k](/packages/pursehouse-modeler-laravel-eloquent)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
