Weave 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

sebastian/type

A collection of value objects that model the PHP type system, including simple, union, intersection, and special types. Use it to inspect, compare, and represent type information programmatically in PHP projects.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What it actually is. sebastian/type is a small set of value objects (SimpleType, ObjectType, UnionType, IntersectionType, StaticType, NullType, VoidType, NeverType, UnknownType) plus a ReflectionMapper that converts ReflectionType into that object model. It has no runtime dependencies, no framework coupling, and no application-facing API surface. It models declared PHP types, not runtime values.

Architecture fit. Good fit for exactly one class of work: tooling that reads signatures and reasons about them — code generation (DTO/model scaffolding, OpenAPI/JSON Schema extraction from return types), custom PHPUnit extensions and assertions, refactoring codemods, IDE-helper-style tooling, and mock return-value synthesis. It is a poor fit for runtime request validation. Laravel's Validator and FormRequest operate on values and rule strings; sebastian/type has no notion of a value, so any plan to "validate API payloads with UnionType" is a category error and should be rejected early. Note also that PHPStan and Psalm do not consume this package — both ship their own type systems (phpstan/phpdoc-parser, Psalm's internal type model). Positioning this as a PHPStan integration is a common and incorrect assumption; correct it before it reaches a roadmap.

Where it already sits. For a Laravel codebase this package is almost certainly already installed transitively via phpunit/phpunit and sebastian/comparator. The decision is therefore not "adopt or not" but "do we take a direct dependency, and do we build on it." That reframes the whole evaluation: this is a supply-chain and test-infrastructure question, not an architecture choice. The Dependents: 0 figure in the package metadata undercounts reality (it reflects direct application-graph dependents, not Composer transitive reach) — confirm with composer why sebastian/type before assuming a greenfield decision.

Integration feasibility. Mechanically trivial: Composer, PSR-4, zero dependencies, BSD-3-Clause. The friction is entirely version policy. Major releases track PHP minor releases aggressively — 6.0 removed PHP 8.2 support, 7.0 removed PHP 8.3 support — so any direct ^ constraint silently becomes a PHP floor. Recent patch history is small but pointed: class-alias resolution in assignability checks (7.0.1, also backported to 6.0.4), and iterable-inside-union handling in ReflectionMapper (6.0.1/6.0.2, backported to 5.1.x). Those are precisely the edge cases that produce confusing test failures rather than clean errors.

Technical risk. Low overall, but concentrated in two places: (1) declaring it directly can gate your PHP upgrade cadence, and (2) it is a single-maintainer package with README-only documentation, no published API stability contract, and release notes as the changelog. Treat its API as effectively internal — usable, but not something to expose across team boundaries or publish in a library's require block.

Key questions.

  1. Is it already present transitively, and which major version does our PHPUnit require? (composer why sebastian/type, composer show sebastian/type)
  2. Do we have any actual code that would call this API, or is this purely inherited from the test stack?
  3. What is our PHP floor today, and does it move with PHPUnit or with the platform team's schedule?
  4. If we build tooling on it, who owns it after the first release — and do they accept a single-maintainer upstream with no support contract?
  5. Does any planned work (contract generation, mock tooling, codemods) already exist as custom reflection code that this would replace? Quantify it.
  6. Are class aliases used in type hints in the codebase we'd analyze? If yes, pin >=6.0.4 / >=7.0.1 at minimum.

Integration Approach

Stack fit. Three tiers, in descending order of realism:

  • Inherited (the default). Nothing to do. It arrives with PHPUnit; we neither constrain nor import it. This is correct for the large majority of Laravel teams and should be the explicit default until a use case is named.
  • Direct, dev-only, for test/CI tooling. Justified when we write custom PHPUnit extensions, assertions, or contract-extraction scripts. require-dev only, constraint aligned to PHPUnit's.
  • Direct, for a shipped internal tool. Only for a standalone codegen/analysis tool in its own repository, where the PHP floor it imposes is the tool's own concern and does not leak into applications or published packages.

What to avoid. Do not add it to a package's require block that other teams consume — that forces our PHP floor onto them. Do not attempt to build runtime validation, casting, or serialization on it; that is a different problem domain. Do not add it as a direct dependency "for safety" when it is already present transitively; that converts a resolved-by-PHPUnit concern into a constraint we now own.

Migration path. There is no migration — this is a verification-and-policy exercise, not a change programme.

  1. Inventory: composer why sebastian/type across the repos in scope; record the resolved version and the pulling package in each.
  2. Baseline the PHP floor per repo and confirm which major the current PHPUnit pins.
  3. If a use case exists, prototype in a scratch branch against the resolved version, not a freshly required one.
  4. Exercise the two known sharp edges first: class-alias assignability and iterable inside unions. If the prototype survives those, the rest is straightforward.
  5. Only then add require-dev with a constraint matching PHPUnit's, and note the coupling in the repo README so the next upgrade doesn't fight it.

Compatibility. Keep the major version synchronized with whatever PHPUnit resolves — independent floating is how you get a Composer conflict on the next PHPUnit bump. Because majors drop PHP minors, prefer a constraint that follows the platform PHP floor rather than racing ahead of it. Verify behaviour on the PHP features we actually use (mixed, never, static, intersection types, enum-adjacent object types) rather than the full type matrix.

Build vs. buy. Writing a reflection-to-type-object mapper for simple and nullable types is a day or two; getting unions, intersections, static types, class aliases, and assignability semantics right is weeks of edge cases. Buying is the right call if we need this capability — but the honest answer for most teams is that they do not, and the correct integration is to leave it exactly where PHPUnit put it.

Sequencing. Verify (week 0) → decide whether any use case exists at all → prototype in a tooling repo, not the application → harden against the alias/union edge cases with regression tests → wire into CI only after the prototype is trusted. Never make it a prerequisite for a product release.

Operational Impact

Maintenance. Near-zero in the inherited case. When it is a direct dependency, maintenance events are not routine patch bumps — they are coupled to PHP and PHPUnit upgrade trains, and a major bump should be scheduled alongside those, not absorbed opportunistically.

Support. No vendor, no SLA, one maintainer, issue tracker as the escalation path. For inherited use this is irrelevant (PHPUnit absorbs it). For direct use, budget for source-reading: the README is a badge wall, so the API is the source. Practically, that means the owning engineer needs to be willing to read the library, not just its docs.

Scaling. Negligible. It is compile-time / dev-time work with no production runtime footprint. The only scaling consideration is reflection cost inside codegen jobs over large codebases — cache mapped types per class rather than re-reflecting in inner loops.

Failure modes, ranked by likelihood.

  1. Composer resolution conflict on the next PHPUnit or PHP upgrade, caused by a direct constraint that drifted from PHPUnit's. Symptom: blocked dependency update. Mitigation: never float the constraint independently.
  2. Silent behaviour change in test tooling after a minor/major bump — for example union/iterable handling or alias resolution shifting, producing odd mock return values or false-negative assertions. Symptom: tests fail for reasons unrelated to the change under review. Mitigation: pin, and upgrade deliberately with a full test run.
  3. UnknownType fallbacks masking types the mapper cannot express, so a codegen or assertion path quietly degrades instead of erroring. Mitigation: fail loudly on UnknownType in our own consumers.
  4. PHP floor break in the CI matrix — a transitive bump raises the required PHP version and the matrix goes red on older jobs. Mitigation: lock files committed, matrix explicitly tied to platform support policy.
  5. Alias-resolution gaps for custom aliases not covered by 7.0.1. Symptom: incorrect assignability verdicts in rare cases. Mitigation: regression test with our own alias patterns if we use them.

Ramp-up. Effectively zero for application developers — nobody writes code against this. Ramp-up applies to the one or two people who own test infrastructure or codegen: an afternoon with the source, focused on ReflectionMapper and assignability semantics, is sufficient. The team-level action is documentation, not training: record which version is pinned, why, and which upstream it follows, so the next upgrade is a lookup rather than an investigation.

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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table