Namespace PHPStan\Type

Classes
AcceptsResult

Result of a Type::accepts() check — whether one type accepts another. Wraps a TrinaryLogic result together with human-readable reasons explaining why the acceptance failed. These reasons are surfaced in PHPStan error messages to help developers understand type mismatches. For example, when checking if int accepts string, the result would be No with a reason like "string is not a subtype of int". The accepts() method is used to check assignability — whether a value of one type can be assigned to a variable/parameter of another type. This is stricter than isSuperTypeOf() because it accounts for PHPStan's rule level and generics variance.

ArrayType
BenevolentUnionType
BooleanType
CallableType
CircularTypeAliasErrorType
ClassStringType
ClosureType
ClosureTypeFactory
ConditionalType
ConditionalTypeForParameter
ConstantTypeHelper
ErrorType
FileTypeMapper
FloatType
GeneralizePrecision

Controls how aggressively Type::generalize() widens a type. Generalization is the process of widening a specific type to a broader one. For example, generalizing ConstantStringType('hello') yields StringType. This is used when PHPStan needs to merge types across loop iterations or branches where tracking precise constant values is impractical. Three levels of precision:

  • lessSpecific: Aggressive generalization — constant values become their general type (e.g. 'hello' → string, array{foo: int} → array<string, int>)
  • moreSpecific: Preserves more detail — e.g. non-empty-string stays non-empty-string instead of widening to string
  • templateArgument: Used when generalizing template type arguments, preserving template-specific structure Used as a parameter to Type::generalize(): $type->generalize(GeneralizePrecision::lessSpecific())
IntegerRangeType
IntegerType
IntersectionType
IsSuperTypeOfResult

Result of a Type::isSuperTypeOf() check — whether one type is a supertype of another. Wraps a TrinaryLogic result together with human-readable reasons explaining the relationship. This is the primary mechanism for comparing types in PHPStan's type system. isSuperTypeOf() answers: "Can all values of type B also be values of type A?" For example:

  • (new StringType())->isSuperTypeOf(new ConstantStringType('hello')) → Yes
  • (new IntegerType())->isSuperTypeOf(new StringType()) → No
  • (new StringType())->isSuperTypeOf(new MixedType()) → Maybe This is distinct from accepts() which also considers rule levels and PHPDoc context. Use isSuperTypeOf() for type-theoretic comparisons and accepts() for assignability checks. Can be converted to AcceptsResult via toAcceptsResult().
IterableType
KeyOfType
MixedType
NeverType
NewObjectType
NonAcceptingNeverType
NullType
ObjectShapeType
ObjectType
ObjectWithoutClassType
OffsetAccessType
ResourceType
SimultaneousTypeTraverser
StaticType
StringType
ThisType
TypeCombinator
TypehintHelper
TypeTraverser
TypeUtils
UnionType
ValueOfType
VerbosityLevel

Controls the verbosity of type descriptions in error messages. When PHPStan describes a type for an error message, it uses VerbosityLevel to decide how much detail to include. Higher levels include more detail like constant values and array shapes. The four levels (from least to most verbose):

  • typeOnly: Just the type name, e.g. "string", "array", "Foo"
  • value: Includes constant values, e.g. "'hello'", "array{foo: int}", "non-empty-string"
  • precise: Maximum detail — adds subtracted types on object/mixed (e.g. "object~Bar"), lowercase/uppercase string distinctions, untruncated array shapes, and template type scope
  • cache: Internal level used for generating cache keys Used as a parameter to Type::describe() to control output detail: $type->describe(VerbosityLevel::typeOnly()) // "string" $type->describe(VerbosityLevel::value()) // "'hello'" $type->describe(VerbosityLevel::precise()) // "non-empty-lowercase-string" The getRecommendedLevelByType() factory method automatically chooses the right level for error messages based on what types are involved — it picks the minimum verbosity needed to distinguish the accepting type from the accepted type.
VoidType
Interfaces
CompoundType

Marker interface for types that require bidirectional type comparison. Simple types like StringType or IntegerType can answer isSuperTypeOf() and accepts() on their own — they check whether the incoming type fits. But compound types (unions, intersections, mixed, never, accessory types, integer ranges, callables, iterables, conditionals, etc.) need to be asked from the other direction, because they carry internal structure that the simple type on the other side knows nothing about. The protocol works like a double dispatch: 1. A simple type's accepts()/isSuperTypeOf() receives an argument. 2. It checks if ($type instanceof CompoundType). 3. If true, it delegates to $type->isAcceptedBy($this, …) or $type->isSubTypeOf($this). 4. The compound type then decomposes itself (e.g., iterates union members) and calls back to the simple type for each component. This avoids the simple type having to understand union/intersection/mixed/never semantics. For example, StringType::accepts() doesn't need to know how to check a UnionType<string|int> — it just delegates to UnionType::isAcceptedBy(), which iterates its members and asks StringType::accepts() for each one. Unlike instanceof SomeSpecificType checks (which are discouraged in CLAUDE.md), instanceof CompoundType is the correct and intended pattern throughout the type system. It is part of the double-dispatch protocol, not a type query. Implementations include:

  • UnionTypeisSubTypeOf() requires ALL members to be subtypes, isAcceptedBy() requires ALL to be accepted
  • IntersectionTypeisSubTypeOf() requires at least ONE member to be a subtype (via maxMin)
  • MixedType, NeverType — terminal cases (mixed accepts everything, never is subtype of everything)
  • All AccessoryType implementations — refinement types that live inside intersections
  • IntegerRangeType, CallableType, IterableType — types with internal structure
  • ConditionalType, KeyOfType, ValueOfType, etc. — late-resolvable types
ConstantScalarType

A type whose value is known at analysis time — a compile-time constant scalar. Implemented by ConstantIntegerType, ConstantFloatType, ConstantStringType, ConstantBooleanType, and NullType. Use Type::isConstantValue() to check if a type is constant without instanceof, and Type::getConstantScalarTypes() to extract constant types from unions.

DynamicFunctionReturnTypeExtension

This is the interface dynamic return type extensions implement for functions. To register it in the configuration file use the phpstan.broker.dynamicFunctionReturnTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.broker.dynamicFunctionReturnTypeExtension

DynamicFunctionThrowTypeExtension

This is the interface dynamic throw type extensions implement for functions. To register it in the configuration file use the phpstan.dynamicFunctionThrowTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.dynamicFunctionThrowTypeExtension

DynamicMethodReturnTypeExtension

This is the interface dynamic return type extensions implement for non-static methods. To register it in the configuration file use the phpstan.broker.dynamicMethodReturnTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.broker.dynamicMethodReturnTypeExtension

DynamicMethodThrowTypeExtension

This is the interface dynamic throw type extensions implement for non-static methods. To register it in the configuration file use the phpstan.dynamicMethodThrowTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.dynamicMethodThrowTypeExtension

DynamicStaticMethodReturnTypeExtension

This is the interface dynamic return type extensions implement for static methods. To register it in the configuration file use the phpstan.broker.dynamicStaticMethodReturnTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.broker.dynamicStaticMethodReturnTypeExtension

DynamicStaticMethodThrowTypeExtension

This is the interface dynamic throw type extensions implement for static methods. To register it in the configuration file use the phpstan.dynamicStaticMethodThrowTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.dynamicStaticMethodThrowTypeExtension

ExpressionTypeResolverExtension

To register it in the configuration file use the phpstan.broker.expressionTypeResolverExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.broker.expressionTypeResolverExtension

FunctionParameterClosureThisExtension

This is the interface for dynamically specifying the $this context for closure parameters in function calls. To register it in the configuration file use the phpstan.functionParameterClosureThisExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.functionParameterClosureThisExtension

FunctionParameterClosureTypeExtension

This is the interface for parameter closure type extensions for functions. To register it in the configuration file use the phpstan.functionParameterClosureTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.functionParameterClosureTypeExtension

FunctionParameterOutTypeExtension

This is the interface dynamic parameter out type extensions implement for functions. To register it in the configuration file use the phpstan.functionParameterOutTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.functionParameterOutTypeExtension

FunctionTypeSpecifyingExtension

This is the interface type-specifying extensions implement for functions. To register it in the configuration file use the phpstan.typeSpecifier.functionTypeSpecifyingExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.typeSpecifier.functionTypeSpecifyingExtension

LateResolvableType
MethodParameterClosureThisExtension

This is the interface for dynamically specifying the $this context for closure parameters in method calls. To register it in the configuration file use the phpstan.methodParameterClosureThisExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.methodParameterClosureThisExtension

MethodParameterClosureTypeExtension

This is the interface for parameter closure type extensions for methods. To register it in the configuration file use the phpstan.methodParameterClosureTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.methodParameterClosureTypeExtension

MethodParameterOutTypeExtension

This is the interface dynamic parameter out type extensions implement for non-static methods. To register it in the configuration file use the phpstan.methodParameterOutTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.methodParameterOutTypeExtension

MethodTypeSpecifyingExtension

This is the interface type-specifying extensions implement for non-static methods. To register it in the configuration file use the phpstan.typeSpecifier.methodTypeSpecifyingExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.typeSpecifier.methodTypeSpecifyingExtension

OperatorTypeSpecifyingExtension

This is the extension interface to implement if you want to describe how arithmetic operators like +, -, *, ^, / should infer types for PHP extensions that overload the behaviour, like GMP. To register it in the configuration file use the phpstan.broker.operatorTypeSpecifyingExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.broker.operatorTypeSpecifyingExtension

StaticMethodParameterClosureThisExtension

This is the interface for dynamically specifying the $this context for closure parameters in static method calls. To register it in the configuration file use the phpstan.staticMethodParameterClosureThisExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.staticMethodParameterClosureThisExtension

StaticMethodParameterClosureTypeExtension

This is the interface for parameter closure type extensions for static methods. To register it in the configuration file use the phpstan.staticMethodParameterClosureTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.staticMethodParameterClosureTypeExtension

StaticMethodParameterOutTypeExtension

This is the interface dynamic parameter out type extensions implement for static methods. To register it in the configuration file use the phpstan.staticMethodParameterOutTypeExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.staticMethodParameterOutTypeExtension

StaticMethodTypeSpecifyingExtension

This is the interface type-specifying extensions implement for static methods. To register it in the configuration file use the phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension service tag: ``` services: - class: App\PHPStan\MyExtension tags: - phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension

Type

Represents a PHPStan type in the type system. This is the central interface of PHPStan's type system. Every type that PHPStan can reason about implements this interface — from simple scalars like StringType to complex generics like GenericObjectType. Each Type knows what it accepts, what is a supertype of it, what properties/methods/constants it has, what operations it supports, and how to describe itself for error messages. Important: Never use instanceof to check types. For example, $type instanceof StringType will miss union types, intersection types with accessory types, and other composite forms. Always use the is*() methods or isSuperTypeOf() instead: // Wrong: if ($type instanceof StringType) { ... } // Correct: if ($type->isString()->yes()) { ... }

TypeTraverserCallable
TypeWithClassName

A Type that represents an object with a known class name. Implemented by ObjectType, StaticType, ThisType, EnumCaseObjectType, ClosureType, and GenericObjectType. Provides access to the class name and its ClassReflection. This interface is used when code needs to work with any object type that has a specific class — for example, Scope::resolveTypeByName() returns TypeWithClassName because the resolved type always has a known class. Note: Do not use instanceof TypeWithClassName to check if a type is an object. Use $type->getObjectClassNames() or $type->isObject() instead, which correctly handles union types and intersection types.

Namespaces
PHPStan\Type\Accessory
PHPStan\Type\Constant
PHPStan\Type\Enum
PHPStan\Type\Generic
PHPStan\Type\Helper
PHPStan\Type\Php