You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enhance documentation for iterators and generators, add ConcreteFileCollection and PluginConfiguration classes, and implement tests for concrete iterable property assignments (#33)
When a method or parameter specifies an abstract stream keyword with inner type constraints:
23
+
```php
24
+
/**
25
+
* Abstract stream contract -> Wrapped in IteratorProxy
26
+
*
27
+
* @param Traversable<string,positive-int> $scores
28
+
*/
29
+
public function processScores(Traversable $scores): void
30
+
```
31
+
Because `Traversable` is a general interface with no methods of its own, TypePHP wraps it in a lazy `IteratorProxy` to validate yielded items and keys during iteration.
When a method parameter, property, or return value is a concrete class (even if that class implements `\IteratorAggregate` or `\Traversable`):
35
+
```php
36
+
class StorefrontConfig
37
+
{
38
+
// Native PHP class type hint
39
+
protected FileCollection $styleFiles;
40
+
41
+
public function setStyleFiles(FileCollection $styleFiles): void
42
+
{
43
+
$this->styleFiles = $styleFiles; // Preserved as raw FileCollection!
44
+
}
45
+
}
46
+
```
47
+
48
+
TypePHP leaves concrete collections **100% unwrapped as raw PHP objects**:
49
+
50
+
***Preserves Native PHP Nominal Type Hints:** Prevents fatal PHP engine errors (e.g. `Cannot assign IteratorProxy to property ...::$styleFiles of type FileCollection`).
51
+
***Preserves Custom Domain Methods & State:** Custom business methods (like `$files->getPublicUrls()` or `$files->filterByExtension()`) and private properties remain directly accessible.
52
+
***Direct `\WeakMap` Enforcement:** For generic concrete classes (like `ArrayCollection<int, Animal>`), TypePHP tracks generic template bindings directly in `\WeakMap` memory, running validation rules inside `$collection->add()` and `$collection->set()` without needing any wrapper proxy!
53
+
***Zero Allocation Overhead:** Eliminates proxy object allocations and garbage collection pressure, allowing concrete collections to run at native C-level speed.
54
+
55
+
### Summary: When TypePHP Wraps vs. Leaves Unwrapped
56
+
57
+
| Type Annotation | Object Passed | Action Taken | Why |
58
+
| :--- | :--- | :---: | :--- |
59
+
|`Traversable<string, positive-int>`| Any Iterator / Generator |**Wrapped in `IteratorProxy`**| Abstract stream; needs lazy item validation during iteration. |
60
+
|`iterable<User>`| Any Array / Traversable |**Wrapped in `IteratorProxy`**| Abstract stream; validates items on-the-fly. |
61
+
|`FileCollection`|`new FileCollection()`|**Unwrapped (Raw Object)**| Concrete class; preserves native PHP type hints and domain methods. |
62
+
|`ArrayCollection<int, Animal>`|`new ArrayCollection()`|**Unwrapped (Raw Object)**| Generic state is tracked directly via `\WeakMap` inside `add()`/`set()`. |
63
+
| Un-annotated (`mixed $items`) | Any Iterator |**Unwrapped (Raw Object)**| No type contracts to enforce; zero overhead. |
0 commit comments