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

Type Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require typhoon/type
    

    Add to composer.json under require-dev if using for type checking/testing.

  2. First Use Case: Define a type for validation or runtime checks:

    use function Typhoon\Type\{stringT, arrayT, objectT, stringify};
    
    $type = arrayT(value: objectT(User::class));
    echo stringify($type); // "array<User>"
    
  3. Key Entry Points:

    • Typhoon\Type\Type (base interface)
    • Type constructors (e.g., stringT(), arrayT(), objectT())
    • stringify() for debugging
    • Typhoon\Type\Visitor for custom operations

Implementation Patterns

1. Type Construction

Workflow: Build complex types hierarchically for validation or runtime checks.

// Define a nested type for API request validation
$requestType = arrayShapeT([
    'user' => objectT(User::class),
    'metadata' => optional(arrayT(stringT, intT)),
]);

// Use in a validator
$validator = new Validator($requestType);
$isValid = $validator->validate($requestData);

Integration Tip:

  • Use arrayShapeT()/objectShapeT() for structured data (e.g., DTOs, API payloads).
  • Combine with optional(), nonEmptyListT(), or unionT() for flexible schemas.

2. Runtime Type Checking

Workflow: Leverage Typhoon\Type\Is for dynamic type validation.

use Typhoon\Type\Is;

$is = new Is();
$result = $is->test($value, stringT()); // bool

Laravel Integration:

  • Use in Form Requests for custom validation:
    public function rules()
    {
        return [
            'data' => ['required', function ($attribute, $value, $fail) {
                $is = new Is();
                if (!$is->test($value, $this->getExpectedType())) {
                    $fail('Invalid data structure.');
                }
            }],
        ];
    }
    

3. Type-Driven Serialization/Deserialization

Workflow: Map between types and data structures (e.g., JSON ↔ PHP objects).

use Typhoon\Type\{arrayShapeT, objectT, nonEmptyListT};

$type = arrayShapeT([
    'users' => nonEmptyListT(objectT(User::class)),
]);

$mapper = new Mapper();
$users = $mapper->map($jsonData, $type); // Decodes + validates

Laravel Use Case:

  • API Request Parsing:
    public function handle(Request $request)
    {
        $type = arrayShapeT(['query' => stringT()]);
        $parsed = (new Mapper())->map($request->all(), $type);
        // $parsed['query'] is guaranteed to be string
    }
    

4. Custom Visitors for Domain-Specific Logic

Workflow: Extend Typhoon\Type\Visitor to add domain logic (e.g., generate OpenAPI schemas).

class OpenApiVisitor implements Visitor
{
    public function visitStringT(StringT $type): string
    {
        return 'string';
    }

    public function visitArrayShapeT(ArrayShapeT $type): string
    {
        $properties = [];
        foreach ($type->shape as $key => $valueType) {
            $properties[$key] = $this->visit($valueType);
        }
        return json_encode(['type' => 'object', 'properties' => $properties]);
    }
    // ... implement other visit methods
}

Laravel Integration:

  • Generate Swagger/OpenAPI specs dynamically:
    $visitor = new OpenApiVisitor();
    $schema = $visitor->visit($requestType);
    

5. Type-Based Dependency Injection

Workflow: Use types to enforce constructor signatures in Laravel’s container.

// Define a type for a service constructor
$serviceType = objectT(Service::class, [stringT(), intT()]);

// In a factory or resolver
$container->when(Service::class)
    ->needsConstructor()
    ->give(function ($c) {
        $args = $c->make([stringT(), intT()]); // Enforced types
        return new Service(...$args);
    });

Gotchas and Tips

Pitfalls

  1. Invariant Generics (0.8.0+):

    • Generic types (e.g., arrayT(K, V)) are invariant by default. Avoid unsafe casts:
      // ❌ Unsafe: arrayT(intT, stringT) is NOT a subtype of arrayT(intT, mixedT)
      $is->test($value, arrayT(intT, mixedT)); // May fail unexpectedly
      
    • Fix: Use unionT() or intersectionT() for broader compatibility.
  2. Null Handling:

    • nullT is distinct from optional(stringT). Explicitly handle null cases:
      $type = unionT(nullT, stringT()); // Accepts both null and string
      
  3. PHPDoc vs. Runtime Types:

    • Some PHPDoc types (e.g., array-key) map to arrayKeyT() but may behave differently at runtime. Test edge cases:
      $is->test('key', arrayKeyT()); // true
      $is->test(123, arrayKeyT());   // false (numeric keys are allowed in PHP arrays)
      
  4. Performance:

    • Complex type hierarchies (e.g., deeply nested arrayShapeT) can slow down validation. Cache Type instances:
      static $cachedType = arrayShapeT([...]); // Reuse instead of recreating
      

Debugging Tips

  1. Use stringify():

    • Debug complex types with:
      echo stringify($type); // Human-readable output
      
  2. Visitor Debugging:

    • Implement a DebugVisitor to trace type traversal:
      class DebugVisitor implements Visitor {
          public function visit($type): void {
              echo "Visiting: " . get_class($type) . "\n";
              // ... delegate to other visit methods
          }
      }
      
  3. Laravel Logging:

    • Log type mismatches for debugging:
      $is = new Is();
      if (!$is->test($value, $expectedType)) {
          Log::error("Type mismatch. Expected: " . stringify($expectedType));
      }
      

Extension Points

  1. Custom Type Constructors:

    • Extend the library by adding new type constructors (e.g., dateT()):
      function dateT(): DateT {
          return new DateT();
      }
      
  2. Visitor Patterns:

    • Add custom visitors for:
      • Code generation (e.g., TypeScript interfaces).
      • Database schema validation.
      • GraphQL schema mapping.
  3. Integration with Laravel Packages:

    • Laravel Scout: Validate search payloads:
      $searchType = arrayShapeT(['query' => stringT(), 'page' => intT()]);
      
    • Lumen API: Enforce request/response types in middleware:
      $middleware->validate($request, $apiType);
      
  4. Testing:

    • Use Typhoon\Type\Is in PHPUnit assertions:
      $this->assertTrue((new Is())->test($value, stringT()));
      

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
andydefer/laravel-cluster
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