typhoon/type
Typhoon Type provides an object abstraction over PHP’s modern type system for building tools that understand complex types. Define, print (stringify), and work with array shapes, object types, non-empty lists, and more in a consistent API.
spatie/laravel-data: Offers more granular control over type constraints (e.g., nonEmptyStringT, intRangeT(-5, 6)) and PHPDoc compatibility, making it suitable for self-documenting APIs.Validator rules with type-driven validation.stringify().objectT(User::class) for belongsTo).composer require typhoon/type (no Laravel-specific dependencies).Typhoon\Type\Mapper) for request/response transformation.Typhoon\Type\Validator.| Risk Area | Mitigation Strategy |
|---|---|
| Performance Overhead | Benchmark Mapper::map() vs. manual validation; cache compiled types if needed. |
| BC Breaks | Version pinning (^0.8) and feature flags for breaking changes (e.g., invariantT). |
| Learning Curve | Document common patterns (e.g., "How to validate a Laravel Form Request"). |
| Runtime vs. Static | Use alongside PHPStan for dual-layer validation (static + runtime). |
| Limited Adoption | Build Laravel-specific wrappers (e.g., Typhoon\Laravel\TypeValidator). |
Illuminate\Validation\Validator)?
TyphoonValidator extending Laravel’s Validator to bridge the gap.stringify() to generate OpenAPI schemas dynamically.Typhoon\Type\Mapper as a singleton for global access.Stringify to output PHPDoc-compatible strings for IDE hints.| Laravel Component | Typhoon Type Use Case |
|---|---|
| Form Requests | Replace rules() with Typhoon\Type\Validator for type-safe validation. |
| API Resources | Define response contracts (e.g., arrayShapeT(['data' => objectT(UserResource::class)])). |
| Eloquent Models | Enforce type-safe relationships (e.g., objectT(User::class) for belongsTo). |
| Events | Validate event payloads (e.g., objectShapeT(['user_id' => intT()])). |
| Middleware | Add Typhoon\Type\ValidateRequest middleware for global type enforcement. |
| Testing | Use Typhoon\Type\Assert in PHPUnit to validate test data. |
| OpenAPI/Swagger | Generate schemas via stringify() for auto-documented APIs. |
Validator rules with Typhoon\Type\Validator.use Typhoon\Type\Validator;
$validator = new Validator([
'name' => nonEmptyStringT(),
'age' => intRangeT(18, 120),
]);
ApiTypes class.final class ApiTypes {
public static function UserResponse(): arrayShapeT {
return arrayShapeT([
'id' => intT(),
'email' => nonEmptyStringT(),
]);
}
}
objectT() for type-safe model relationships.class Post extends Model {
public function user(): BelongsTo {
return $this->belongsTo(User::class)
->setTypeHint(objectT(User::class)); // Enforce type safety
}
}
assertArrayHasKey() with Typhoon\Type\Assert.stringify() for IDE support.nullOrT(arrayT())) for gradual adoption.rules()).Validator rules with declarative types.stringify() improves developer experience.intRangeT)."Expected non-empty-string, got ''").nonEmptyStringT vs. stringT.arrayShapeT vs. arrayT.arrayShapeT) in Laravel’s cache.save()).arrayShapeT(['user' => objectT(UserDTO::class)])).| Scenario | Mitigation |
|---|---|
| Invalid API payload | Return 422 Unprocessable Entity with Typhoon error details. |
| Type mismatch in DB | Use Typhoon\Type\Assert in model observers to catch inconsistencies. |
| Performance regression | Profile Mapper::map() |
How can I help you explore Laravel packages today?