rector/type-perfect
Type Perfect adds 10 PHPStan rules to tighten type declarations: replace empty/isset checks with instanceof for precise narrowing, prefer explicit getters over magic array access, and enforce interface signatures. Easy to enable even on legacy code; improves reliability fast.
Keeping 2 very close packages up-to-date is daunting work and keep both behind. T Both focus with custom PHPStan rule on better type coverage and more precise and narrow types if available.
To improve support, the Type Perfect rules have been merged into tomasvotruba/type-coverage as of its 2.3.0 release. This is the final release of rector/type-perfect — it is marked abandoned in composer.json and Composer will now point you at the replacement on every install.
"require-dev": {
- "rector/type-perfect": "^2.1"
+ "tomasvotruba/type-coverage": "^2.3"
}
composer remove rector/type-perfect --dev
composer require tomasvotruba/type-coverage --dev
If you already use tomasvotruba/type-coverage, only remove rector/type-perfect — keeping both loads every rule twice.
Type Coverage requires PHP ^8.4; Type Perfect required ^8.2.
ignoreErrors as they areThe rules keep the Rector\TypePerfect\ namespace inside Type Coverage, so existing ignore patterns and PHPStan baselines still match. The extension is registered by phpstan/extension-installer, so no includes change is needed either.
NoParamTypeRemovalRule, NoIssetOnObjectRule and NoEmptyOnObjectRule reported right after install here. In Type Coverage they are opt-in like the rest of the set, one parameter each:
parameters:
type_perfect:
narrow_param: true
narrow_return: true
no_mixed_property: true
no_mixed_caller: true
null_over_false: true
+ no_param_type_removal: true
+ no_isset_on_object: true
+ no_empty_on_object: true
Every other parameter name is unchanged.
NoArrayAccessOnObjectRule — the $object['key'] over $object->getKey() check is not part of Type Coverage. If you rely on it, pin rector/type-perfect:2.2.0 alongside Type Coverage with only that rule enabled.
$id = $article['id']; // bad - no idea what the type is
$id = $article->getId(); // good - we know it is int
Two fixes released here after the merge are not in Type Coverage yet: the NarrowPublicClassMethodParamTypeRule generic-object false-positive (#74) and the Symfony DomCrawler skip in NoArrayAccessOnObjectRule (#77).
How can I help you explore Laravel packages today?