No transpilation. No build steps. No C-extensions.
Drop TypePHP into your existing codebase and let your DocBlocks scream when types fail.
TypePHP is a transparent, pure-PHP runtime type checker. You don't have to refactor a single line of your codebase, set up complex build toolchains, or compile C-extensions. Simply run your existing code, and TypePHP will enforce your extended PHPDoc contracts (generics, array shapes, key-of/value-of extractions, and scalar refinements) dynamically at runtime.
Read the full TypePHP documentation »
When a type contract fails, web exception handlers (Laravel Ignition, Symfony ErrorHandler, Whoops) and CLI test runners (Pest, PHPUnit) highlight the exact line of code in your application where the invalid data was passed, with zero line-drift:
Prevent dynamic data bugs from leaking into database queries or API responses:
namespace App\Models;
use App\Enums\Role;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* @return list<int>
*/
public function assignableRoles(): array
{
if ($this->isSuperAdmin()) {
// Bug! Returns an array of Role Enum instances instead of integers:
return Role::cases();
}
return [Role::STAFF->value];
}
}
// Executing $user->assignableRoles() throws:
// TypePHP\Exception\TypeError: User::assignableRoles(): Return value[0] must be of type int, App\Enums\Role returnedDefine generic templates and TypePHP tracks their state per object instance in memory using native \WeakMap:
/**
* @template T
*/
class Collection
{
/** @param T $item */
public function add(mixed $item): void { /* ... */ }
}
// Prebind T = User to this specific instance in WeakMap memory
/** @var Collection<User> $users */
$users = new Collection();
$users->add(new User('Alice')); // Valid
$users->add(new Product('SKU-100'));
// Throws TypeError: Argument $item (template T = User) must be of type User, Product givenEnforce strict associative array structures and constant key/value extractions:
namespace App\Services;
use App\Database\DriverManager;
/**
* @phpstan-type ConnectionParams array{
* driver: key-of<DriverManager::DRIVER_MAP>,
* driverClass?: value-of<DriverManager::DRIVER_MAP>
* }
*/
class DatabaseService
{
/**
* @param ConnectionParams $params
*/
public function connect(array $params): void
{
// ...
}
}
$service = new DatabaseService();
$service->connect(['driver' => 'pdo_mysql']); // Valid
$service->connect(['driver' => 'pdo_invalid']);
// Throws TypeError: Argument $params['driver'] must be a key of DriverManager::DRIVER_MAPAll the documentation lives on the typephp-php.github.io/docs website:
- Getting Started & Installation Guide
- Quick Start Guide
- Configuration Guide
- CLI Commands Reference
- Runtime Generics (Flagship)
- Enforcement Boundaries: Function Contracts
- Supported Types: Arrays & Shapes
- Architecture: How It Works
- Official Blog & Announcements
- Troubleshooting & FAQ
TypePHP is conceptually inspired by Python's Beartype, bringing transparent runtime type enforcement for type annotations to the PHP ecosystem without any decorators or attributes.
Want to support the open-source development and maintenance of TypePHP? Sponsor me on GitHub »
Any contributions are welcome. Feel free to open issues or submit pull requests on GitHub.
TypePHP is open-source software licensed under the MIT License.


