Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions docs/collection/api/collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ count(): int
Returns the number of elements in the collection.

```php
countWhere(Closure $predicate): int
countWhere(Closure $predicate): int<0, max>
```
Returns the number of elements matching the predicate `(E, int): bool`.

Expand Down Expand Up @@ -135,7 +135,7 @@ Reduce, or `null` if empty.
```php
sum(?Closure $selector = null): int|float
```
Sum of all elements, or values returned by the selector `(E, int): int|float`.
Sum of all elements, or values returned by the selector `(E, int): int|float`. The return type narrows to `int` when every summed value is an `int` — a `Collection<int>`, or a selector declared to return `int` — and stays `int|float` otherwise.

```php
avg(?Closure $selector = null): float
Expand Down Expand Up @@ -168,22 +168,22 @@ maxOrNull(?Closure $selector = null): E|null
Maximum element, or `null` if empty. Optional selector `(E, int): mixed`.

```php
minOf(Closure $selector): mixed
minOf(Closure $selector): R
```
Returns the minimum value produced by the selector `(E, int): mixed`. Unlike `min()`, returns the **selector value** itself, not the element. Throws `NoSuchElementException` if empty.
Returns the minimum value produced by the selector `(E, int): R`. Unlike `min()`, returns the **selector value** itself, not the element. The return type follows the selector — one declared `: int` yields `int`. Throws `NoSuchElementException` if empty.

```php
minOfOrNull(Closure $selector): mixed
minOfOrNull(Closure $selector): R|null
```
Returns the minimum selector value, or `null` if empty.

```php
maxOf(Closure $selector): mixed
maxOf(Closure $selector): R
```
Returns the maximum value produced by the selector `(E, int): mixed`. Unlike `max()`, returns the **selector value** itself, not the element. Throws `NoSuchElementException` if empty.
Returns the maximum value produced by the selector `(E, int): R`. Unlike `max()`, returns the **selector value** itself, not the element. The return type follows the selector — one declared `: int` yields `int`. Throws `NoSuchElementException` if empty.

```php
maxOfOrNull(Closure $selector): mixed
maxOfOrNull(Closure $selector): R|null
```
Returns the maximum selector value, or `null` if empty.

Expand Down Expand Up @@ -216,7 +216,7 @@ Filter by predicate `(E, int): bool`. Returns `ImmutableList` for lists, `Immuta
```php
filterNotNull(): Collection<E>
```
Filter out `null` elements.
Filter out `null` elements. The element type narrows to exclude `null` — `Collection<string|null>` becomes `Collection<string>`.

```php
filterInstanceOf(string $type): Collection<T>
Expand All @@ -239,9 +239,9 @@ flatMap(Closure $transform): Collection<R>
Transform and flatten. Closure: `(E, int): iterable<R>`.

```php
flatten(): Collection<mixed>
flatten(): Collection<V>
```
Flatten a collection of iterables.
Flatten a collection of iterables, one level deep. Iterable elements contribute their own values (`V` is the element type of `E`); non-iterable elements are kept as-is. So `Collection<ImmutableList<int>>` becomes `Collection<int>`, `Collection<array<int>|string>` becomes `Collection<int|string>`, and `Collection<string>` stays `Collection<string>`. Only one level is removed — flattening `Collection<ImmutableList<ImmutableList<int>>>` yields `Collection<ImmutableList<int>>`.

```php
takeFirst(int $n = 1): Collection<E>
Expand Down
8 changes: 4 additions & 4 deletions docs/collection/api/map.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ count(): int
Returns the number of entries in the map.

```php
countWhere(Closure $predicate): int
countWhere(Closure $predicate): int<0, max>
```
Returns the number of entries matching the predicate `(V, K): bool`.

Expand Down Expand Up @@ -135,7 +135,7 @@ Filter by value predicate `(V): bool`.
```php
filterValuesNotNull(): ImmutableMap<K,V>
```
Exclude entries with `null` values.
Exclude entries with `null` values. The value type narrows to exclude `null` — `Map<string, int|null>` becomes `Map<string, int>`. Keys are preserved.

```php
filterValuesInstanceOf(string $type): ImmutableMap<K,T>
Expand Down Expand Up @@ -235,9 +235,9 @@ flatMap(Closure $transform): ImmutableList<R>
Transform each entry with `(V, K): iterable<R>` and flatten all results into a single list.

```php
toArray(KeyCollisionStrategy $onCollision = KeyCollisionStrategy::Throw): array
toArray(KeyCollisionStrategy $onCollision = KeyCollisionStrategy::Throw): array<K,V>
```
Convert to PHP array. Only works with scalar keys. Throws `ConversionException` for object keys or key collisions.
Convert to PHP array. Only works with scalar keys. Throws `ConversionException` for object keys or key collisions. The key type is preserved when `K` is a valid array key — a `Map<string, int>` yields `array<string, int>`; a map with keys PHP cannot use natively falls back to `array<array-key, V>`.

```php
toPairs(): list<array{0:K, 1:V}>
Expand Down
4 changes: 3 additions & 1 deletion tests/Type/Collection/TransformTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
assertType('Noctud\Collection\Collection<int>', $c->map(fn (string $x): int => (int) $x));
assertType('Noctud\Collection\Collection<int>', $c->mapNotNull(fn (string $x): ?int => $x !== '' ? 1 : null));
assertType('Noctud\Collection\Collection<int>', $c->flatMap(fn (string $x): array => [(int) $x]));
assertType('Noctud\Collection\Collection<mixed>', $c->flatten());

// flatten() keeps non-iterable elements as-is; see FlattenTypeTest for the nesting cases.
assertType('Noctud\Collection\Collection<string>', $c->flatten());

// Slicing preserves the element type.
assertType('Noctud\Collection\Collection<string>', $c->takeFirst(2));
Expand Down
Loading