Psl Noise - 4.0.0
This release marks a major update for the PHP Standard Library, introducing several breaking changes aimed at improving strictness, consistency, and developer experience. The library is now much stricter in its type handling and serialization, and the static analysis has been migrated to a more powerful tool.
🚀 Breaking Changes
💥 Psl\Result\wrap()
No Longer Unwraps Nested Results
To reduce surprising behavior, Psl\Result\wrap()
will no longer automatically unwrap a Result
instance returned from within the wrapped closure. It will now consistently wrap the closure's return value in a Success
object, even if that value is itself a Result
.
Before:
$result = Psl\Result\wrap(fn() => Psl\Result\wrap(fn() => 'hello'));
// $result is Success('hello')
After:
$result = Psl\Result\wrap(fn() => Psl\Result\wrap(fn() => 'hello'));
// $result is Success(Success('hello'))
💥 JSON Serialization for Collections
The JSON serialization for Map
and Set
collections has been changed to provide a more natural and predictable representation.
Psl\Collection\Map
andPsl\Collection\MutableMap
now serialize to a JSON object ({...}
) in all cases, even when empty or when containing sequential integer keys. This ensures a consistent key-value structure.Psl\Collection\Set
andPsl\Collection\MutableSet
now serialize to a JSON array ([...]
), which better represents a collection of unique values.
💥 Removal of IO Intersection Interfaces
A large number of intersection interfaces in the Psl\IO
and Psl\File
namespaces have been removed to simplify the component's hierarchy. These interfaces were combinations of other interfaces (e.g., CloseReadHandleInterface
as CloseHandleInterface&ReadHandleInterface
).
Developers should now use union types or explicit interface checks where needed. For example, instead of type-hinting CloseReadHandleInterface
, use CloseHandleInterface&ReadHandleInterface
.
💥 Psl\sequence()
Function Removed
The Psl\sequence()
function, which returned the last argument it received, has been removed as it provided little practical value.
✨ New Features
Psl\Type\container()
A new container<Tk, Tv>
type has been added to assert that a value is an iterable
with specific key and value types. Unlike iterable()
, it will coerce the value to an array
.
Psl\Type\int_range()
The new int_range(int $min, int $max)
type allows asserting that a value is an integer within a specified range. It supports the same coercions as the int()
type.
Psl\Type\always_assert()
This new type wrapper ensures that the inner type is always asserted, even during coercion. This is useful for disabling coercion on a per-type basis.
Psl\Iter\search_with_keys()
and search_with_keys_opt()
These functions provide the ability to search an iterable using a predicate that receives both the key and the value, returning the value of the first match.
♻️ Refactoring and Improvements
- Static Analysis Migration: The project has migrated from
Psalm
toMago
for static analysis, resulting in stricter type checking and improved code quality. Many internal@psalm-suppress
annotations have been removed. - Improved Type Inference: PHPDoc annotations across
Dict
,Iter
,Regex
, andVec
have been enhanced with conditional types. This allows static analysis tools to infer more precise types, especially for non-empty arrays and regex match results, reducing the need for user-land assertions. - Generic PHPDoc Tags: Psalm-specific tags like
@psalm-pure
have been replaced with the more generic@pure
to reduce dependency on a single tool.
⬆️ Dependency Updates
mago
has been updated to1.0.0-beta.15
.actions/checkout
has been bumped from v4 to v5 in GitHub Actions.- Other minor dependency updates.
🤝 New Contributors
Full Changelog: 3.3.0...4.0.0