diff --git a/.github/workflows/types.yml b/.github/workflows/types.yml new file mode 100644 index 000000000000..31b13134caf6 --- /dev/null +++ b/.github/workflows/types.yml @@ -0,0 +1,43 @@ +name: types + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +jobs: + linux_tests: + runs-on: ubuntu-20.04 + + strategy: + fail-fast: true + matrix: + php: ['8.0'] + include: + - php: '8.1' + flags: "--ignore-platform-req=php" + + name: PHP ${{ matrix.php }} + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + tools: composer:v2 + coverage: none + + - name: Install dependencies + uses: nick-invision/retry@v1 + with: + timeout_minutes: 5 + max_attempts: 5 + command: composer update --prefer-stable --prefer-dist --no-interaction --no-progress ${{ matrix.flags }} + + - name: Execute type checking + continue-on-error: ${{ matrix.php > 8 }} + run: vendor/bin/phpstan diff --git a/composer.json b/composer.json index 6032d975078a..72ade6dee3a8 100644 --- a/composer.json +++ b/composer.json @@ -88,6 +88,7 @@ "mockery/mockery": "^1.4.3", "orchestra/testbench-core": "^7.0", "pda/pheanstalk": "^4.0", + "phpstan/phpstan": "^0.12.94", "phpunit/phpunit": "^9.4", "predis/predis": "^1.1.2", "symfony/cache": "^5.3" diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 000000000000..609d438c7593 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,4 @@ +parameters: + paths: + - types + level: max diff --git a/src/Illuminate/Collections/Collection.php b/src/Illuminate/Collections/Collection.php index cbde79e64eb5..c5cdf2381327 100644 --- a/src/Illuminate/Collections/Collection.php +++ b/src/Illuminate/Collections/Collection.php @@ -8,21 +8,31 @@ use Illuminate\Support\Traits\Macroable; use stdClass; +/** + * @template TKey of array-key + * @template TValue + * + * @implements \ArrayAccess + * @implements \Illuminate\Support\Enumerable + */ class Collection implements ArrayAccess, Enumerable { + /** + * @use \Illuminate\Support\Traits\EnumeratesValues + */ use EnumeratesValues, Macroable; /** * The items contained in the collection. * - * @var array + * @var array */ protected $items = []; /** * Create a new collection. * - * @param mixed $items + * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items * @return void */ public function __construct($items = []) @@ -35,7 +45,7 @@ public function __construct($items = []) * * @param int $from * @param int $to - * @return static + * @return static */ public static function range($from, $to) { @@ -45,7 +55,7 @@ public static function range($from, $to) /** * Get all of the items in the collection. * - * @return array + * @return array */ public function all() { @@ -65,8 +75,8 @@ public function lazy() /** * Get the average value of a given key. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue): float|int)|string|null $callback + * @return float|int|null */ public function avg($callback = null) { @@ -86,8 +96,8 @@ public function avg($callback = null) /** * Get the median of a given key. * - * @param string|array|null $key - * @return mixed + * @param string|array|null $key + * @return float|int|null */ public function median($key = null) { @@ -116,8 +126,8 @@ public function median($key = null) /** * Get the mode of a given key. * - * @param string|array|null $key - * @return array|null + * @param string|array|null $key + * @return array|null */ public function mode($key = null) { @@ -145,7 +155,7 @@ public function mode($key = null) /** * Collapse the collection of items into a single array. * - * @return static + * @return static */ public function collapse() { @@ -155,7 +165,7 @@ public function collapse() /** * Determine if an item exists in the collection. * - * @param mixed $key + * @param (callable(TValue): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -178,8 +188,11 @@ public function contains($key, $operator = null, $value = null) /** * Cross join with the given lists, returning all possible permutations. * - * @param mixed ...$lists - * @return static + * @template TCrossJoinKey + * @template TCrossJoinValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$lists + * @return static> */ public function crossJoin(...$lists) { @@ -191,8 +204,8 @@ public function crossJoin(...$lists) /** * Get the items in the collection that are not present in the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function diff($items) { @@ -202,9 +215,9 @@ public function diff($items) /** * Get the items in the collection that are not present in the given items, using the callback. * - * @param mixed $items - * @param callable $callback - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @param callable(TValue): int $callback + * @return static */ public function diffUsing($items, callable $callback) { @@ -214,8 +227,8 @@ public function diffUsing($items, callable $callback) /** * Get the items in the collection whose keys and values are not present in the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function diffAssoc($items) { @@ -225,9 +238,9 @@ public function diffAssoc($items) /** * Get the items in the collection whose keys and values are not present in the given items, using the callback. * - * @param mixed $items - * @param callable $callback - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @param callable(TKey): int $callback + * @return static */ public function diffAssocUsing($items, callable $callback) { @@ -237,8 +250,8 @@ public function diffAssocUsing($items, callable $callback) /** * Get the items in the collection whose keys are not present in the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function diffKeys($items) { @@ -248,9 +261,9 @@ public function diffKeys($items) /** * Get the items in the collection whose keys are not present in the given items, using the callback. * - * @param mixed $items - * @param callable $callback - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @param callable(TKey): int $callback + * @return static */ public function diffKeysUsing($items, callable $callback) { @@ -260,9 +273,9 @@ public function diffKeysUsing($items, callable $callback) /** * Retrieve duplicate items from the collection. * - * @param callable|string|null $callback + * @param (callable(TValue): bool)|string|null $callback * @param bool $strict - * @return static + * @return static */ public function duplicates($callback = null, $strict = false) { @@ -288,8 +301,8 @@ public function duplicates($callback = null, $strict = false) /** * Retrieve duplicate items from the collection using strict comparison. * - * @param callable|string|null $callback - * @return static + * @param (callable(TValue): bool)|string|null $callback + * @return static */ public function duplicatesStrict($callback = null) { @@ -300,7 +313,7 @@ public function duplicatesStrict($callback = null) * Get the comparison function to detect duplicates. * * @param bool $strict - * @return \Closure + * @return callable(TValue, TValue): bool */ protected function duplicateComparator($strict) { @@ -318,8 +331,8 @@ protected function duplicateComparator($strict) /** * Get all items except for those with the specified keys. * - * @param \Illuminate\Support\Collection|mixed $keys - * @return static + * @param \Illuminate\Support\Enumerable|array $keys + * @return static */ public function except($keys) { @@ -335,8 +348,8 @@ public function except($keys) /** * Run a filter over each of the items. * - * @param callable|null $callback - * @return static + * @param (callable(TValue): bool)|null $callback + * @return static */ public function filter(callable $callback = null) { @@ -350,9 +363,11 @@ public function filter(callable $callback = null) /** * Get the first item from the collection passing the given truth test. * - * @param callable|null $callback - * @param mixed $default - * @return mixed + * @template TFirstDefault + * + * @param (callable(TValue): bool)|null $callback + * @param TFirstDefault $default + * @return TValue|TFirstDefault */ public function first(callable $callback = null, $default = null) { @@ -363,7 +378,7 @@ public function first(callable $callback = null, $default = null) * Get a flattened array of the items in the collection. * * @param int $depth - * @return static + * @return static */ public function flatten($depth = INF) { @@ -373,7 +388,7 @@ public function flatten($depth = INF) /** * Flip the items in the collection. * - * @return static + * @return static */ public function flip() { @@ -383,7 +398,7 @@ public function flip() /** * Remove an item from the collection by key. * - * @param string|array $keys + * @param TKey|array $keys * @return $this */ public function forget($keys) @@ -398,9 +413,11 @@ public function forget($keys) /** * Get an item from the collection by key. * - * @param mixed $key - * @param mixed $default - * @return mixed + * @template TGetDefault + * + * @param TKey $key + * @param TGetDefault $default + * @return TValue|TGetDefault */ public function get($key, $default = null) { @@ -414,9 +431,9 @@ public function get($key, $default = null) /** * Group an associative array by a field or using a callback. * - * @param array|callable|string $groupBy + * @param (callable(TValue, TKey): array-key)|array|string $groupBy * @param bool $preserveKeys - * @return static + * @return static> */ public function groupBy($groupBy, $preserveKeys = false) { @@ -460,8 +477,8 @@ public function groupBy($groupBy, $preserveKeys = false) /** * Key an associative array by a field or using a callback. * - * @param callable|string $keyBy - * @return static + * @param (callable(TValue, TKey): array-key)|array|string $keyBy + * @return static> */ public function keyBy($keyBy) { @@ -485,7 +502,7 @@ public function keyBy($keyBy) /** * Determine if an item exists in the collection by key. * - * @param mixed $key + * @param TKey|array $key * @return bool */ public function has($key) @@ -522,8 +539,8 @@ public function implode($value, $glue = null) /** * Intersect the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function intersect($items) { @@ -533,8 +550,8 @@ public function intersect($items) /** * Intersect the collection with the given items by key. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function intersectByKeys($items) { @@ -596,7 +613,7 @@ public function join($glue, $finalGlue = '') /** * Get the keys of the collection items. * - * @return static + * @return static */ public function keys() { @@ -606,9 +623,11 @@ public function keys() /** * Get the last item from the collection. * - * @param callable|null $callback - * @param mixed $default - * @return mixed + * @template TLastDefault + * + * @param (callable(TValue, TKey): bool)|null $callback + * @param TLastDefault $default + * @return TValue|TLastDefault */ public function last(callable $callback = null, $default = null) { @@ -618,9 +637,9 @@ public function last(callable $callback = null, $default = null) /** * Get the values of a given key. * - * @param string|array|int|null $value + * @param string|array $value * @param string|null $key - * @return static + * @return static */ public function pluck($value, $key = null) { @@ -630,8 +649,10 @@ public function pluck($value, $key = null) /** * Run a map over each of the items. * - * @param callable $callback - * @return static + * @template TMapValue + * + * @param callable(TValue, TKey): TMapValue $callback + * @return static */ public function map(callable $callback) { @@ -647,8 +668,11 @@ public function map(callable $callback) * * The callback should return an associative array with a single key/value pair. * - * @param callable $callback - * @return static + * @template TMapToDictionaryKey of array-key + * @template TMapToDictionaryValue + * + * @param callable(TValue, TKey): array $callback + * @return static> */ public function mapToDictionary(callable $callback) { @@ -676,8 +700,11 @@ public function mapToDictionary(callable $callback) * * The callback should return an associative array with a single key/value pair. * - * @param callable $callback - * @return static + * @template TMapWithKeysKey of array-key + * @template TMapWithKeysValue + * + * @param callable(TValue, TKey): array $callback + * @return static */ public function mapWithKeys(callable $callback) { @@ -697,8 +724,8 @@ public function mapWithKeys(callable $callback) /** * Merge the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function merge($items) { @@ -708,8 +735,8 @@ public function merge($items) /** * Recursively merge the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static> */ public function mergeRecursive($items) { @@ -719,8 +746,10 @@ public function mergeRecursive($items) /** * Create a collection by using this collection for keys and another for its values. * - * @param mixed $values - * @return static + * @template TCombineValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function combine($values) { @@ -730,8 +759,8 @@ public function combine($values) /** * Union the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function union($items) { @@ -743,7 +772,7 @@ public function union($items) * * @param int $step * @param int $offset - * @return static + * @return static */ public function nth($step, $offset = 0) { @@ -765,8 +794,8 @@ public function nth($step, $offset = 0) /** * Get the items with the specified keys. * - * @param mixed $keys - * @return static + * @param \Illuminate\Support\Enumerable|array $keys + * @return static */ public function only($keys) { @@ -787,7 +816,7 @@ public function only($keys) * Get and remove the last N items from the collection. * * @param int $count - * @return mixed + * @return static|TValue|null */ public function pop($count = 1) { @@ -813,8 +842,8 @@ public function pop($count = 1) /** * Push an item onto the beginning of the collection. * - * @param mixed $value - * @param mixed $key + * @param TValue $value + * @param TKey $key * @return $this */ public function prepend($value, $key = null) @@ -827,7 +856,7 @@ public function prepend($value, $key = null) /** * Push one or more items onto the end of the collection. * - * @param mixed $values [optional] + * @param ...TValue $values * @return $this */ public function push(...$values) @@ -842,8 +871,8 @@ public function push(...$values) /** * Push all of the given items onto the collection. * - * @param iterable $source - * @return static + * @param iterable $source + * @return static */ public function concat($source) { @@ -859,9 +888,11 @@ public function concat($source) /** * Get and remove an item from the collection. * - * @param mixed $key - * @param mixed $default - * @return mixed + * @template TPullDefault + * + * @param TKey $key + * @param TPullDefault $default + * @return TValue|TPullDefault */ public function pull($key, $default = null) { @@ -871,8 +902,8 @@ public function pull($key, $default = null) /** * Put an item in the collection by key. * - * @param mixed $key - * @param mixed $value + * @param TKey $key + * @param TValue $value * @return $this */ public function put($key, $value) @@ -886,7 +917,7 @@ public function put($key, $value) * Get one or a specified number of items randomly from the collection. * * @param int|null $number - * @return static|mixed + * @return static|TValue * * @throws \InvalidArgumentException */ @@ -902,8 +933,8 @@ public function random($number = null) /** * Replace the collection items with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function replace($items) { @@ -913,8 +944,8 @@ public function replace($items) /** * Recursively replace the collection items with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function replaceRecursive($items) { @@ -924,7 +955,7 @@ public function replaceRecursive($items) /** * Reverse items order. * - * @return static + * @return static */ public function reverse() { @@ -934,9 +965,9 @@ public function reverse() /** * Search the collection for a given value and return the corresponding key if successful. * - * @param mixed $value + * @param TValue|(callable(TValue,TKey): bool) $value * @param bool $strict - * @return mixed + * @return TKey|bool */ public function search($value, $strict = false) { @@ -957,7 +988,7 @@ public function search($value, $strict = false) * Get and remove the first N items from the collection. * * @param int $count - * @return mixed + * @return static|TValue|null */ public function shift($count = 1) { @@ -984,7 +1015,7 @@ public function shift($count = 1) * Shuffle the items in the collection. * * @param int|null $seed - * @return static + * @return static */ public function shuffle($seed = null) { @@ -996,7 +1027,7 @@ public function shuffle($seed = null) * * @param int $size * @param int $step - * @return static + * @return static> */ public function sliding($size = 2, $step = 1) { @@ -1011,7 +1042,7 @@ public function sliding($size = 2, $step = 1) * Skip the first {$count} items. * * @param int $count - * @return static + * @return static */ public function skip($count) { @@ -1021,8 +1052,8 @@ public function skip($count) /** * Skip items in the collection until the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function skipUntil($value) { @@ -1032,8 +1063,8 @@ public function skipUntil($value) /** * Skip items in the collection while the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function skipWhile($value) { @@ -1045,7 +1076,7 @@ public function skipWhile($value) * * @param int $offset * @param int|null $length - * @return static + * @return static */ public function slice($offset, $length = null) { @@ -1056,7 +1087,7 @@ public function slice($offset, $length = null) * Split a collection into a certain number of groups. * * @param int $numberOfGroups - * @return static + * @return static> */ public function split($numberOfGroups) { @@ -1093,7 +1124,7 @@ public function split($numberOfGroups) * Split a collection into a certain number of groups, and fill the first groups completely. * * @param int $numberOfGroups - * @return static + * @return static> */ public function splitIn($numberOfGroups) { @@ -1103,10 +1134,10 @@ public function splitIn($numberOfGroups) /** * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception. * - * @param mixed $key + * @param (callable(TValue, TKey): bool)|string $key * @param mixed $operator * @param mixed $value - * @return mixed + * @return TValue * * @throws \Illuminate\Support\ItemNotFoundException * @throws \Illuminate\Support\MultipleItemsFoundException @@ -1159,7 +1190,7 @@ public function firstOrFail($key = null, $operator = null, $value = null) * Chunk the collection into chunks of the given size. * * @param int $size - * @return static + * @return static> */ public function chunk($size) { @@ -1179,8 +1210,8 @@ public function chunk($size) /** * Chunk the collection into chunks with a callback. * - * @param callable $callback - * @return static + * @param callable(TValue, TKey, static): bool $callback + * @return static> */ public function chunkWhile(callable $callback) { @@ -1192,8 +1223,8 @@ public function chunkWhile(callable $callback) /** * Sort through each item with a callback. * - * @param callable|int|null $callback - * @return static + * @param (callable(TValue, TValue): bool)|null|int $callback + * @return static */ public function sort($callback = null) { @@ -1210,7 +1241,7 @@ public function sort($callback = null) * Sort items in descending order. * * @param int $options - * @return static + * @return static */ public function sortDesc($options = SORT_REGULAR) { @@ -1224,10 +1255,10 @@ public function sortDesc($options = SORT_REGULAR) /** * Sort the collection using the given callback. * - * @param callable|array|string $callback + * @param (callable(TValue, TKey): mixed)|string $callback * @param int $options * @param bool $descending - * @return static + * @return static */ public function sortBy($callback, $options = SORT_REGULAR, $descending = false) { @@ -1306,9 +1337,9 @@ protected function sortByMany(array $comparisons = []) /** * Sort the collection in descending order using the given callback. * - * @param callable|string $callback + * @param (callable(TValue, TKey): mixed)|string $callback * @param int $options - * @return static + * @return static */ public function sortByDesc($callback, $options = SORT_REGULAR) { @@ -1320,7 +1351,7 @@ public function sortByDesc($callback, $options = SORT_REGULAR) * * @param int $options * @param bool $descending - * @return static + * @return static */ public function sortKeys($options = SORT_REGULAR, $descending = false) { @@ -1335,7 +1366,7 @@ public function sortKeys($options = SORT_REGULAR, $descending = false) * Sort the collection keys in descending order. * * @param int $options - * @return static + * @return static */ public function sortKeysDesc($options = SORT_REGULAR) { @@ -1347,8 +1378,8 @@ public function sortKeysDesc($options = SORT_REGULAR) * * @param int $offset * @param int|null $length - * @param mixed $replacement - * @return static + * @param array $replacement + * @return static */ public function splice($offset, $length = null, $replacement = []) { @@ -1363,7 +1394,7 @@ public function splice($offset, $length = null, $replacement = []) * Take the first or last {$limit} items. * * @param int $limit - * @return static + * @return static */ public function take($limit) { @@ -1377,8 +1408,8 @@ public function take($limit) /** * Take items in the collection until the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function takeUntil($value) { @@ -1388,8 +1419,8 @@ public function takeUntil($value) /** * Take items in the collection while the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function takeWhile($value) { @@ -1399,7 +1430,7 @@ public function takeWhile($value) /** * Transform each item in the collection using a callback. * - * @param callable $callback + * @param callable(TValue, TKey): TValue $callback * @return $this */ public function transform(callable $callback) @@ -1412,7 +1443,7 @@ public function transform(callable $callback) /** * Reset the keys on the underlying array. * - * @return static + * @return static */ public function values() { @@ -1425,8 +1456,10 @@ public function values() * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]); * => [[1, 4], [2, 5], [3, 6]] * - * @param mixed ...$items - * @return static + * @template TZipValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$items + * @return static> */ public function zip($items) { @@ -1444,9 +1477,11 @@ public function zip($items) /** * Pad collection to the specified length with a value. * + * @template TPadValue + * * @param int $size - * @param mixed $value - * @return static + * @param TPadValue $value + * @return static */ public function pad($size, $value) { @@ -1456,7 +1491,7 @@ public function pad($size, $value) /** * Get an iterator for the items. * - * @return \ArrayIterator + * @return \ArrayIterator */ #[\ReturnTypeWillChange] public function getIterator() @@ -1478,8 +1513,8 @@ public function count() /** * Count the number of items in the collection by a field or using a callback. * - * @param callable|string $countBy - * @return static + * @param (callable(TValue, TKey): mixed)|string|null $countBy + * @return static */ public function countBy($countBy = null) { @@ -1489,7 +1524,7 @@ public function countBy($countBy = null) /** * Add an item to the collection. * - * @param mixed $item + * @param TValue $item * @return $this */ public function add($item) @@ -1502,7 +1537,7 @@ public function add($item) /** * Get a base Support collection instance from this collection. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function toBase() { @@ -1512,7 +1547,7 @@ public function toBase() /** * Determine if an item exists at an offset. * - * @param mixed $key + * @param TKey $key * @return bool */ #[\ReturnTypeWillChange] @@ -1524,8 +1559,8 @@ public function offsetExists($key) /** * Get an item at a given offset. * - * @param mixed $key - * @return mixed + * @param TKey $key + * @return TValue */ #[\ReturnTypeWillChange] public function offsetGet($key) @@ -1536,8 +1571,8 @@ public function offsetGet($key) /** * Set the item at a given offset. * - * @param mixed $key - * @param mixed $value + * @param TKey|null $key + * @param TValue $value * @return void */ #[\ReturnTypeWillChange] @@ -1553,7 +1588,7 @@ public function offsetSet($key, $value) /** * Unset the item at a given offset. * - * @param string $key + * @param TKey $key * @return void */ #[\ReturnTypeWillChange] diff --git a/src/Illuminate/Collections/Enumerable.php b/src/Illuminate/Collections/Enumerable.php index 59109e719e0f..c16e23077a6b 100644 --- a/src/Illuminate/Collections/Enumerable.php +++ b/src/Illuminate/Collections/Enumerable.php @@ -8,13 +8,23 @@ use IteratorAggregate; use JsonSerializable; +/** + * @template TKey of array-key + * @template TValue + * + * @extends \Illuminate\Contracts\Support\Arrayable + * @extends \IteratorAggregate + */ interface Enumerable extends Arrayable, Countable, IteratorAggregate, Jsonable, JsonSerializable { /** * Create a new collection instance if the value isn't one already. * - * @param mixed $items - * @return static + * @template TMakeKey of array-key + * @template TMakeValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items + * @return static */ public static function make($items = []); @@ -39,23 +49,29 @@ public static function range($from, $to); /** * Wrap the given value in a collection if applicable. * - * @param mixed $value - * @return static + * @template TWrapKey of array-key + * @template TWrapValue + * + * @param iterable $value + * @return static */ public static function wrap($value); /** * Get the underlying items from the given collection if applicable. * - * @param array|static $value - * @return array + * @template TUnwrapKey of array-key + * @template TUnwrapValue + * + * @param array|static $value + * @return array */ public static function unwrap($value); /** * Create a new instance with no items. * - * @return static + * @return static */ public static function empty(); @@ -69,38 +85,38 @@ public function all(); /** * Alias for the "avg" method. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue): float|int)|string|null $callback + * @return float|int|null */ public function average($callback = null); /** * Get the median of a given key. * - * @param string|array|null $key - * @return mixed + * @param string|array|null $key + * @return float|int|null */ public function median($key = null); /** * Get the mode of a given key. * - * @param string|array|null $key - * @return array|null + * @param string|array|null $key + * @return array|null */ public function mode($key = null); /** * Collapse the items into a single enumerable. * - * @return static + * @return static */ public function collapse(); /** * Alias for the "contains" method. * - * @param mixed $key + * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -110,8 +126,8 @@ public function some($key, $operator = null, $value = null); /** * Determine if an item exists, using strict comparison. * - * @param mixed $key - * @param mixed $value + * @param (callable(TValue): bool)|TValue|string $key + * @param TValue|null $value * @return bool */ public function containsStrict($key, $value = null); @@ -119,15 +135,15 @@ public function containsStrict($key, $value = null); /** * Get the average value of a given key. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue): float|int)|string|null $callback + * @return float|int|null */ public function avg($callback = null); /** * Determine if an item exists in the enumerable. * - * @param mixed $key + * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -137,8 +153,11 @@ public function contains($key, $operator = null, $value = null); /** * Cross join with the given lists, returning all possible permutations. * - * @param mixed ...$lists - * @return static + * @template TCrossJoinKey + * @template TCrossJoinValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$lists + * @return static> */ public function crossJoin(...$lists); @@ -146,7 +165,7 @@ public function crossJoin(...$lists); * Dump the collection and end the script. * * @param mixed ...$args - * @return void + * @return never */ public function dd(...$args); @@ -160,75 +179,75 @@ public function dump(); /** * Get the items that are not present in the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function diff($items); /** * Get the items that are not present in the given items, using the callback. * - * @param mixed $items - * @param callable $callback - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @param callable(TValue): int $callback + * @return static */ public function diffUsing($items, callable $callback); /** * Get the items whose keys and values are not present in the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function diffAssoc($items); /** * Get the items whose keys and values are not present in the given items, using the callback. * - * @param mixed $items - * @param callable $callback - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @param callable(TKey): int $callback + * @return static */ public function diffAssocUsing($items, callable $callback); /** * Get the items whose keys are not present in the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function diffKeys($items); /** * Get the items whose keys are not present in the given items, using the callback. * - * @param mixed $items - * @param callable $callback - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @param callable(TKey): int $callback + * @return static */ public function diffKeysUsing($items, callable $callback); /** * Retrieve duplicate items. * - * @param callable|string|null $callback + * @param (callable(TValue): bool)|string|null $callback * @param bool $strict - * @return static + * @return static */ public function duplicates($callback = null, $strict = false); /** * Retrieve duplicate items using strict comparison. * - * @param callable|string|null $callback - * @return static + * @param (callable(TValue): bool)|string|null $callback + * @return static */ public function duplicatesStrict($callback = null); /** * Execute a callback over each item. * - * @param callable $callback + * @param callable(TValue): mixed $callback * @return $this */ public function each(callable $callback); @@ -236,15 +255,15 @@ public function each(callable $callback); /** * Execute a callback over each nested chunk of items. * - * @param callable $callback - * @return static + * @param callable(...mixed): mixed $callback + * @return static */ public function eachSpread(callable $callback); /** * Determine if all items pass the given truth test. * - * @param string|callable $key + * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -254,72 +273,84 @@ public function every($key, $operator = null, $value = null); /** * Get all items except for those with the specified keys. * - * @param mixed $keys - * @return static + * @param \Illuminate\Support\Enumerable|array $keys + * @return static */ public function except($keys); /** * Run a filter over each of the items. * - * @param callable|null $callback - * @return static + * @param (callable(TValue): bool)|null $callback + * @return static */ public function filter(callable $callback = null); /** * Apply the callback if the given "value" is (or resolves to) truthy. * + * @template TWhenReturnType as null + * * @param bool $value - * @param callable|null $callback - * @param callable|null $default - * @return static|mixed + * @param (callable($this): TWhenReturnType)|null $callback + * @param (callable($this): TWhenReturnType)|null $default + * @return $this|TWhenReturnType */ public function when($value, callable $callback = null, callable $default = null); /** * Apply the callback if the collection is empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TWhenEmptyReturnType + * + * @param (callable($this): TWhenEmptyReturnType) $callback + * @param (callable($this): TWhenEmptyReturnType)|null $default + * @return $this|TWhenEmptyReturnType */ public function whenEmpty(callable $callback, callable $default = null); /** * Apply the callback if the collection is not empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TWhenNotEmptyReturnType + * + * @param callable($this): TWhenNotEmptyReturnType $callback + * @param (callable($this): TWhenNotEmptyReturnType)|null $default + * @return $this|TWhenNotEmptyReturnType */ public function whenNotEmpty(callable $callback, callable $default = null); /** * Apply the callback if the given "value" is (or resolves to) truthy. * + * @template TWhenReturnType + * * @param bool $value - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @param (callable($this): TUnlessReturnType) $callback + * @param (callable($this): TUnlessReturnType)|null $default + * @return $this|TUnlessReturnType */ public function unless($value, callable $callback, callable $default = null); /** * Apply the callback unless the collection is empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TUnlessEmptyReturnType + * + * @param callable($this): TUnlessEmptyReturnType $callback + * @param (callable($this): TUnlessEmptyReturnType)|null $default + * @return $this|TUnlessEmptyReturnType */ public function unlessEmpty(callable $callback, callable $default = null); /** * Apply the callback unless the collection is not empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TUnlessNotEmptyReturnType + * + * @param callable($this): TUnlessNotEmptyReturnType $callback + * @param (callable($this): TUnlessNotEmptyReturnType)|null $default + * @return $this|TUnlessNotEmptyReturnType */ public function unlessNotEmpty(callable $callback, callable $default = null); @@ -329,7 +360,7 @@ public function unlessNotEmpty(callable $callback, callable $default = null); * @param string $key * @param mixed $operator * @param mixed $value - * @return static + * @return static */ public function where($key, $operator = null, $value = null); @@ -337,7 +368,7 @@ public function where($key, $operator = null, $value = null); * Filter items where the value for the given key is null. * * @param string|null $key - * @return static + * @return static */ public function whereNull($key = null); @@ -345,7 +376,7 @@ public function whereNull($key = null); * Filter items where the value for the given key is not null. * * @param string|null $key - * @return static + * @return static */ public function whereNotNull($key = null); @@ -354,7 +385,7 @@ public function whereNotNull($key = null); * * @param string $key * @param mixed $value - * @return static + * @return static */ public function whereStrict($key, $value); @@ -362,9 +393,9 @@ public function whereStrict($key, $value); * Filter items by the given key value pair. * * @param string $key - * @param mixed $values + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values * @param bool $strict - * @return static + * @return static */ public function whereIn($key, $values, $strict = false); @@ -372,8 +403,8 @@ public function whereIn($key, $values, $strict = false); * Filter items by the given key value pair using strict comparison. * * @param string $key - * @param mixed $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereInStrict($key, $values); @@ -381,8 +412,8 @@ public function whereInStrict($key, $values); * Filter items such that the value of the given key is between the given values. * * @param string $key - * @param array $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereBetween($key, $values); @@ -390,8 +421,8 @@ public function whereBetween($key, $values); * Filter items such that the value of the given key is not between the given values. * * @param string $key - * @param array $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereNotBetween($key, $values); @@ -399,9 +430,9 @@ public function whereNotBetween($key, $values); * Filter items by the given key value pair. * * @param string $key - * @param mixed $values + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values * @param bool $strict - * @return static + * @return static */ public function whereNotIn($key, $values, $strict = false); @@ -409,25 +440,27 @@ public function whereNotIn($key, $values, $strict = false); * Filter items by the given key value pair using strict comparison. * * @param string $key - * @param mixed $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereNotInStrict($key, $values); /** * Filter the items, removing any items that don't match the given type(s). * - * @param string|string[] $type - * @return static + * @param class-string|array $type + * @return static */ public function whereInstanceOf($type); /** * Get the first item from the enumerable passing the given truth test. * - * @param callable|null $callback - * @param mixed $default - * @return mixed + * @template TFirstDefault + * + * @param (callable(TValue): bool)|null $callback + * @param TFirstDefault $default + * @return TValue|TFirstDefault */ public function first(callable $callback = null, $default = null); @@ -437,7 +470,7 @@ public function first(callable $callback = null, $default = null); * @param string $key * @param mixed $operator * @param mixed $value - * @return mixed + * @return TValue|null */ public function firstWhere($key, $operator = null, $value = null); @@ -445,47 +478,49 @@ public function firstWhere($key, $operator = null, $value = null); * Get a flattened array of the items in the collection. * * @param int $depth - * @return static + * @return static */ public function flatten($depth = INF); /** * Flip the values with their keys. * - * @return static + * @return static */ public function flip(); /** * Get an item from the collection by key. * - * @param mixed $key - * @param mixed $default - * @return mixed + * @template TGetDefault + * + * @param TKey $key + * @param TGetDefault $default + * @return TValue|TGetDefault */ public function get($key, $default = null); /** * Group an associative array by a field or using a callback. * - * @param array|callable|string $groupBy + * @param (callable(TValue, TKey): array-key)|array|string $groupBy * @param bool $preserveKeys - * @return static + * @return static> */ public function groupBy($groupBy, $preserveKeys = false); /** * Key an associative array by a field or using a callback. * - * @param callable|string $keyBy - * @return static + * @param (callable(TValue, TKey): array-key)|array|string $keyBy + * @return static> */ public function keyBy($keyBy); /** * Determine if an item exists in the collection by key. * - * @param mixed $key + * @param TKey|array $key * @return bool */ public function has($key); @@ -502,16 +537,16 @@ public function implode($value, $glue = null); /** * Intersect the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function intersect($items); /** * Intersect the collection with the given items by key. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function intersectByKeys($items); @@ -541,32 +576,38 @@ public function join($glue, $finalGlue = ''); /** * Get the keys of the collection items. * - * @return static + * @return static */ public function keys(); /** * Get the last item from the collection. * - * @param callable|null $callback - * @param mixed $default - * @return mixed + * @template TLastDefault + * + * @param (callable(TValue, TKey): bool)|null $callback + * @param TLastDefault $default + * @return TValue|TLastDefault */ public function last(callable $callback = null, $default = null); /** * Run a map over each of the items. * - * @param callable $callback - * @return static + * @template TMapValue + * + * @param callable(TValue, TKey): TMapValue $callback + * @return static */ public function map(callable $callback); /** * Run a map over each nested chunk of items. * - * @param callable $callback - * @return static + * @template TMapSpreadValue + * + * @param callable(...mixed): TMapSpreadValue $callback + * @return static */ public function mapSpread(callable $callback); @@ -575,8 +616,11 @@ public function mapSpread(callable $callback); * * The callback should return an associative array with a single key/value pair. * - * @param callable $callback - * @return static + * @template TMapToDictionaryKey of array-key + * @template TMapToDictionaryValue + * + * @param callable(TValue, TKey): array $callback + * @return static> */ public function mapToDictionary(callable $callback); @@ -585,8 +629,11 @@ public function mapToDictionary(callable $callback); * * The callback should return an associative array with a single key/value pair. * - * @param callable $callback - * @return static + * @template TMapToGroupsKey of array-key + * @template TMapToGroupsValue + * + * @param callable(TValue, TKey): array $callback + * @return static> */ public function mapToGroups(callable $callback); @@ -595,72 +642,77 @@ public function mapToGroups(callable $callback); * * The callback should return an associative array with a single key/value pair. * - * @param callable $callback - * @return static + * @template TMapWithKeysKey of array-key + * @template TMapWithKeysValue + * + * @param callable(TValue, TKey): array $callback + * @return static */ public function mapWithKeys(callable $callback); /** * Map a collection and flatten the result by a single level. * - * @param callable $callback - * @return static + * @param callable(TValue, TKey): mixed $callback + * @return static */ public function flatMap(callable $callback); /** * Map the values into a new class. * - * @param string $class - * @return static + * @param class-string $class + * @return static */ public function mapInto($class); /** * Merge the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function merge($items); /** * Recursively merge the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static> */ public function mergeRecursive($items); /** * Create a collection by using this collection for keys and another for its values. * - * @param mixed $values - * @return static + * @template TCombineValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function combine($values); /** * Union the collection with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function union($items); /** * Get the min value of a given key. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue):mixed)|string|null $callback + * @return TValue */ public function min($callback = null); /** * Get the max value of a given key. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue):mixed)|string|null $callback + * @return TValue */ public function max($callback = null); @@ -669,15 +721,15 @@ public function max($callback = null); * * @param int $step * @param int $offset - * @return static + * @return static */ public function nth($step, $offset = 0); /** * Get the items with the specified keys. * - * @param mixed $keys - * @return static + * @param \Illuminate\Support\Enumerable|array $keys + * @return static */ public function only($keys); @@ -686,25 +738,25 @@ public function only($keys); * * @param int $page * @param int $perPage - * @return static + * @return static */ public function forPage($page, $perPage); /** * Partition the collection into two arrays using the given callback or key. * - * @param callable|string $key + * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value - * @return static + * @return array> */ public function partition($key, $operator = null, $value = null); /** * Push all of the given items onto the collection. * - * @param iterable $source - * @return static + * @param iterable $source + * @return static */ public function concat($source); @@ -712,7 +764,7 @@ public function concat($source); * Get one or a specified number of items randomly from the collection. * * @param int|null $number - * @return static|mixed + * @return static|TValue * * @throws \InvalidArgumentException */ @@ -721,41 +773,44 @@ public function random($number = null); /** * Reduce the collection to a single value. * - * @param callable $callback - * @param mixed $initial - * @return mixed + * @template TReduceInitial + * @template TReduceReturnType + * + * @param callable(TReduceInitial|TReduceReturnType, TValue): TReduceReturnType $callback + * @param TReduceInitial $initial + * @return TReduceReturnType */ public function reduce(callable $callback, $initial = null); /** * Replace the collection items with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function replace($items); /** * Recursively replace the collection items with the given items. * - * @param mixed $items - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $items + * @return static */ public function replaceRecursive($items); /** * Reverse items order. * - * @return static + * @return static */ public function reverse(); /** * Search the collection for a given value and return the corresponding key if successful. * - * @param mixed $value + * @param TValue|callable(TValue,TKey): bool $value * @param bool $strict - * @return mixed + * @return TKey|bool */ public function search($value, $strict = false); @@ -763,7 +818,7 @@ public function search($value, $strict = false); * Shuffle the items in the collection. * * @param int|null $seed - * @return static + * @return static */ public function shuffle($seed = null); @@ -771,23 +826,23 @@ public function shuffle($seed = null); * Skip the first {$count} items. * * @param int $count - * @return static + * @return static */ public function skip($count); /** * Skip items in the collection until the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function skipUntil($value); /** * Skip items in the collection while the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function skipWhile($value); @@ -796,7 +851,7 @@ public function skipWhile($value); * * @param int $offset * @param int|null $length - * @return static + * @return static */ public function slice($offset, $length = null); @@ -804,17 +859,17 @@ public function slice($offset, $length = null); * Split a collection into a certain number of groups. * * @param int $numberOfGroups - * @return static + * @return static> */ public function split($numberOfGroups); /** * Get the first item in the collection, but only if exactly one item exists. Otherwise, throw an exception. * - * @param mixed $key + * @param (callable(TValue, TKey): bool)|string $key * @param mixed $operator * @param mixed $value - * @return mixed + * @return TValue * * @throws \Illuminate\Support\ItemNotFoundException * @throws \Illuminate\Support\MultipleItemsFoundException @@ -825,23 +880,23 @@ public function sole($key = null, $operator = null, $value = null); * Chunk the collection into chunks of the given size. * * @param int $size - * @return static + * @return static> */ public function chunk($size); /** * Chunk the collection into chunks with a callback. * - * @param callable $callback - * @return static + * @param callable(TValue, TKey, static): bool $callback + * @return static> */ public function chunkWhile(callable $callback); /** * Sort through each item with a callback. * - * @param callable|null|int $callback - * @return static + * @param (callable(TValue, TValue): bool)|null|int $callback + * @return static */ public function sort($callback = null); @@ -849,26 +904,26 @@ public function sort($callback = null); * Sort items in descending order. * * @param int $options - * @return static + * @return static */ public function sortDesc($options = SORT_REGULAR); /** * Sort the collection using the given callback. * - * @param callable|string $callback + * @param (callable(TValue, TKey): mixed)|string $callback * @param int $options * @param bool $descending - * @return static + * @return static */ public function sortBy($callback, $options = SORT_REGULAR, $descending = false); /** * Sort the collection in descending order using the given callback. * - * @param callable|string $callback + * @param (callable(TValue, TKey): mixed)|string $callback * @param int $options - * @return static + * @return static */ public function sortByDesc($callback, $options = SORT_REGULAR); @@ -877,7 +932,7 @@ public function sortByDesc($callback, $options = SORT_REGULAR); * * @param int $options * @param bool $descending - * @return static + * @return static */ public function sortKeys($options = SORT_REGULAR, $descending = false); @@ -885,14 +940,14 @@ public function sortKeys($options = SORT_REGULAR, $descending = false); * Sort the collection keys in descending order. * * @param int $options - * @return static + * @return static */ public function sortKeysDesc($options = SORT_REGULAR); /** * Get the sum of the given values. * - * @param callable|string|null $callback + * @param (callable(TValue): mixed)|string|null $callback * @return mixed */ public function sum($callback = null); @@ -901,30 +956,30 @@ public function sum($callback = null); * Take the first or last {$limit} items. * * @param int $limit - * @return static + * @return static */ public function take($limit); /** * Take items in the collection until the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function takeUntil($value); /** * Take items in the collection while the given condition is met. * - * @param mixed $value - * @return static + * @param TValue|callable(TValue,TKey): bool $value + * @return static */ public function takeWhile($value); /** * Pass the collection to the given callback and then return it. * - * @param callable $callback + * @param callable(TValue): mixed $callback * @return $this */ public function tap(callable $callback); @@ -932,66 +987,70 @@ public function tap(callable $callback); /** * Pass the enumerable to the given callback and return the result. * - * @param callable $callback - * @return mixed + * @template TPipeReturnType + * + * @param callable($this): TPipeReturnType $callback + * @return TPipeReturnType */ public function pipe(callable $callback); /** * Get the values of a given key. * - * @param string|array $value + * @param string|array $value * @param string|null $key - * @return static + * @return static */ public function pluck($value, $key = null); /** * Create a collection of all elements that do not pass a given truth test. * - * @param callable|mixed $callback - * @return static + * @param (callable(TValue): bool)|bool $callback + * @return static */ public function reject($callback = true); /** * Return only unique items from the collection array. * - * @param string|callable|null $key + * @param (callable(TValue, TKey): bool)|string|null $key * @param bool $strict - * @return static + * @return static */ public function unique($key = null, $strict = false); /** * Return only unique items from the collection array using strict comparison. * - * @param string|callable|null $key - * @return static + * @param (callable(TValue, TKey): bool)|string|null $key + * @return static */ public function uniqueStrict($key = null); /** * Reset the keys on the underlying array. * - * @return static + * @return static */ public function values(); /** * Pad collection to the specified length with a value. * + * @template TPadValue + * * @param int $size - * @param mixed $value - * @return static + * @param TPadValue $value + * @return static */ public function pad($size, $value); /** * Count the number of items in the collection using a given truth test. * - * @param callable|null $callback - * @return static + * @param (callable(TValue, TKey): mixed)|string|null $callback + * @return static */ public function countBy($callback = null); @@ -1001,15 +1060,17 @@ public function countBy($callback = null); * e.g. new Collection([1, 2, 3])->zip([4, 5, 6]); * => [[1, 4], [2, 5], [3, 6]] * - * @param mixed ...$items - * @return static + * @template TZipValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$items + * @return static> */ public function zip($items); /** * Collect the values into a collection. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function collect(); diff --git a/src/Illuminate/Collections/Traits/EnumeratesValues.php b/src/Illuminate/Collections/Traits/EnumeratesValues.php index 530bfe3bd321..09487fd2ad0d 100644 --- a/src/Illuminate/Collections/Traits/EnumeratesValues.php +++ b/src/Illuminate/Collections/Traits/EnumeratesValues.php @@ -16,6 +16,9 @@ use Traversable; /** + * @template TKey of array-key + * @template TValue + * * @property-read HigherOrderCollectionProxy $average * @property-read HigherOrderCollectionProxy $avg * @property-read HigherOrderCollectionProxy $contains @@ -51,7 +54,7 @@ trait EnumeratesValues /** * The methods that can be proxied. * - * @var string[] + * @var array */ protected static $proxies = [ 'average', @@ -86,8 +89,11 @@ trait EnumeratesValues /** * Create a new collection instance if the value isn't one already. * - * @param mixed $items - * @return static + * @template TMakeKey of array-key + * @template TMakeValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $items + * @return static */ public static function make($items = []) { @@ -97,8 +103,11 @@ public static function make($items = []) /** * Wrap the given value in a collection if applicable. * - * @param mixed $value - * @return static + * @template TWrapKey of array-key + * @template TWrapValue + * + * @param iterable $value + * @return static */ public static function wrap($value) { @@ -110,8 +119,11 @@ public static function wrap($value) /** * Get the underlying items from the given collection if applicable. * - * @param array|static $value - * @return array + * @template TUnwrapKey of array-key + * @template TUnwrapValue + * + * @param array|static $value + * @return array */ public static function unwrap($value) { @@ -121,7 +133,7 @@ public static function unwrap($value) /** * Create a new instance with no items. * - * @return static + * @return static */ public static function empty() { @@ -131,9 +143,11 @@ public static function empty() /** * Create a new collection by invoking the callback a given amount of times. * + * @template TTimesValue + * * @param int $number - * @param callable|null $callback - * @return static + * @param (callable(int): TTimesValue)|null $callback + * @return static */ public static function times($number, callable $callback = null) { @@ -149,8 +163,8 @@ public static function times($number, callable $callback = null) /** * Alias for the "avg" method. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue): float|int)|string|null $callback + * @return float|int|null */ public function average($callback = null) { @@ -160,7 +174,7 @@ public function average($callback = null) /** * Alias for the "contains" method. * - * @param mixed $key + * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -173,8 +187,8 @@ public function some($key, $operator = null, $value = null) /** * Determine if an item exists, using strict comparison. * - * @param mixed $key - * @param mixed $value + * @param (callable(TValue): bool)|TValue|string $key + * @param TValue|null $value * @return bool */ public function containsStrict($key, $value = null) @@ -202,7 +216,7 @@ public function containsStrict($key, $value = null) * Dump the items and end the script. * * @param mixed ...$args - * @return void + * @return never */ public function dd(...$args) { @@ -230,7 +244,7 @@ public function dump() /** * Execute a callback over each item. * - * @param callable $callback + * @param callable(TValue): mixed $callback * @return $this */ public function each(callable $callback) @@ -247,8 +261,8 @@ public function each(callable $callback) /** * Execute a callback over each nested chunk of items. * - * @param callable $callback - * @return static + * @param callable(...mixed): mixed $callback + * @return static */ public function eachSpread(callable $callback) { @@ -262,7 +276,7 @@ public function eachSpread(callable $callback) /** * Determine if all items pass the given truth test. * - * @param string|callable $key + * @param (callable(TValue, TKey): bool)|TValue|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -290,7 +304,7 @@ public function every($key, $operator = null, $value = null) * @param string $key * @param mixed $operator * @param mixed $value - * @return mixed + * @return TValue|null */ public function firstWhere($key, $operator = null, $value = null) { @@ -310,8 +324,10 @@ public function isNotEmpty() /** * Run a map over each nested chunk of items. * - * @param callable $callback - * @return static + * @template TMapSpreadValue + * + * @param callable(mixed): TMapSpreadValue $callback + * @return static */ public function mapSpread(callable $callback) { @@ -327,8 +343,11 @@ public function mapSpread(callable $callback) * * The callback should return an associative array with a single key/value pair. * - * @param callable $callback - * @return static + * @template TMapToGroupsKey of array-key + * @template TMapToGroupsValue + * + * @param callable(TValue, TKey): array $callback + * @return static> */ public function mapToGroups(callable $callback) { @@ -340,8 +359,8 @@ public function mapToGroups(callable $callback) /** * Map a collection and flatten the result by a single level. * - * @param callable $callback - * @return static + * @param callable(TValue, TKey): mixed $callback + * @return static */ public function flatMap(callable $callback) { @@ -351,8 +370,8 @@ public function flatMap(callable $callback) /** * Map the values into a new class. * - * @param string $class - * @return static + * @param class-string $class + * @return static */ public function mapInto($class) { @@ -364,8 +383,8 @@ public function mapInto($class) /** * Get the min value of a given key. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue):mixed)|string|null $callback + * @return TValue */ public function min($callback = null) { @@ -383,8 +402,8 @@ public function min($callback = null) /** * Get the max value of a given key. * - * @param callable|string|null $callback - * @return mixed + * @param (callable(TValue):mixed)|string|null $callback + * @return TValue */ public function max($callback = null) { @@ -416,10 +435,10 @@ public function forPage($page, $perPage) /** * Partition the collection into two arrays using the given callback or key. * - * @param callable|string $key - * @param mixed $operator - * @param mixed $value - * @return static + * @param (callable(TValue, TKey): bool)|TValue|string $key + * @param TValue|string|null $operator + * @param TValue|null $value + * @return array> */ public function partition($key, $operator = null, $value = null) { @@ -444,7 +463,7 @@ public function partition($key, $operator = null, $value = null) /** * Get the sum of the given values. * - * @param callable|string|null $callback + * @param (callable(TValue): mixed)|string|null $callback * @return mixed */ public function sum($callback = null) @@ -461,9 +480,11 @@ public function sum($callback = null) /** * Apply the callback if the collection is empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TWhenEmptyReturnType + * + * @param (callable($this): TWhenEmptyReturnType) $callback + * @param (callable($this): TWhenEmptyReturnType)|null $default + * @return $this|TWhenEmptyReturnType */ public function whenEmpty(callable $callback, callable $default = null) { @@ -473,9 +494,11 @@ public function whenEmpty(callable $callback, callable $default = null) /** * Apply the callback if the collection is not empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TWhenNotEmptyReturnType + * + * @param callable($this): TWhenNotEmptyReturnType $callback + * @param (callable($this): TWhenNotEmptyReturnType)|null $default + * @return $this|TWhenNotEmptyReturnType */ public function whenNotEmpty(callable $callback, callable $default = null) { @@ -485,9 +508,11 @@ public function whenNotEmpty(callable $callback, callable $default = null) /** * Apply the callback unless the collection is empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TUnlessEmptyReturnType + * + * @param callable($this): TUnlessEmptyReturnType $callback + * @param (callable($this): TUnlessEmptyReturnType)|null $default + * @return $this|TUnlessEmptyReturnType */ public function unlessEmpty(callable $callback, callable $default = null) { @@ -497,9 +522,11 @@ public function unlessEmpty(callable $callback, callable $default = null) /** * Apply the callback unless the collection is not empty. * - * @param callable $callback - * @param callable|null $default - * @return static|mixed + * @template TUnlessNotEmptyReturnType + * + * @param callable($this): TUnlessNotEmptyReturnType $callback + * @param (callable($this): TUnlessNotEmptyReturnType)|null $default + * @return $this|TUnlessNotEmptyReturnType */ public function unlessNotEmpty(callable $callback, callable $default = null) { @@ -512,7 +539,7 @@ public function unlessNotEmpty(callable $callback, callable $default = null) * @param string $key * @param mixed $operator * @param mixed $value - * @return static + * @return static */ public function where($key, $operator = null, $value = null) { @@ -523,7 +550,7 @@ public function where($key, $operator = null, $value = null) * Filter items where the value for the given key is null. * * @param string|null $key - * @return static + * @return static */ public function whereNull($key = null) { @@ -534,7 +561,7 @@ public function whereNull($key = null) * Filter items where the value for the given key is not null. * * @param string|null $key - * @return static + * @return static */ public function whereNotNull($key = null) { @@ -546,7 +573,8 @@ public function whereNotNull($key = null) * * @param string $key * @param mixed $value - * @return static + * @param bool $strict + * @return static */ public function whereStrict($key, $value) { @@ -557,9 +585,9 @@ public function whereStrict($key, $value) * Filter items by the given key value pair. * * @param string $key - * @param mixed $values + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values * @param bool $strict - * @return static + * @return static */ public function whereIn($key, $values, $strict = false) { @@ -574,8 +602,8 @@ public function whereIn($key, $values, $strict = false) * Filter items by the given key value pair using strict comparison. * * @param string $key - * @param mixed $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereInStrict($key, $values) { @@ -586,8 +614,8 @@ public function whereInStrict($key, $values) * Filter items such that the value of the given key is between the given values. * * @param string $key - * @param array $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereBetween($key, $values) { @@ -598,8 +626,8 @@ public function whereBetween($key, $values) * Filter items such that the value of the given key is not between the given values. * * @param string $key - * @param array $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereNotBetween($key, $values) { @@ -612,9 +640,9 @@ public function whereNotBetween($key, $values) * Filter items by the given key value pair. * * @param string $key - * @param mixed $values + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values * @param bool $strict - * @return static + * @return static */ public function whereNotIn($key, $values, $strict = false) { @@ -629,8 +657,8 @@ public function whereNotIn($key, $values, $strict = false) * Filter items by the given key value pair using strict comparison. * * @param string $key - * @param mixed $values - * @return static + * @param \Illuminate\Contracts\Support\Arrayable|iterable $values + * @return static */ public function whereNotInStrict($key, $values) { @@ -640,8 +668,8 @@ public function whereNotInStrict($key, $values) /** * Filter the items, removing any items that don't match the given type(s). * - * @param string|string[] $type - * @return static + * @param class-string|array $type + * @return static */ public function whereInstanceOf($type) { @@ -663,8 +691,10 @@ public function whereInstanceOf($type) /** * Pass the collection to the given callback and return the result. * - * @param callable $callback - * @return mixed + * @template TPipeReturnType + * + * @param callable($this): TPipeReturnType $callback + * @return TPipeReturnType */ public function pipe(callable $callback) { @@ -674,7 +704,7 @@ public function pipe(callable $callback) /** * Pass the collection into a new class. * - * @param string $class + * @param string-class $class * @return mixed */ public function pipeInto($class) @@ -685,9 +715,12 @@ public function pipeInto($class) /** * Reduce the collection to a single value. * - * @param callable $callback - * @param mixed $initial - * @return mixed + * @template TReduceInitial + * @template TReduceReturnType + * + * @param callable(TReduceInitial|TReduceReturnType, TValue): TReduceReturnType $callback + * @param TReduceInitial $initial + * @return TReduceReturnType */ public function reduce(callable $callback, $initial = null) { @@ -703,9 +736,12 @@ public function reduce(callable $callback, $initial = null) /** * Reduce an associative collection to a single value. * - * @param callable $callback - * @param mixed $initial - * @return mixed + * @template TReduceWithKeysInitial + * @template TReduceWithKeysReturnType + * + * @param callable(TReduceWithKeysInitial|TReduceWithKeysReturnType, TValue): TReduceWithKeysReturnType $callback + * @param TReduceWithKeysInitial $initial + * @return TReduceWithKeysReturnType */ public function reduceWithKeys(callable $callback, $initial = null) { @@ -715,8 +751,8 @@ public function reduceWithKeys(callable $callback, $initial = null) /** * Create a collection of all elements that do not pass a given truth test. * - * @param callable|mixed $callback - * @return static + * @param (callable(TValue): bool)|bool $callback + * @return static */ public function reject($callback = true) { @@ -732,7 +768,7 @@ public function reject($callback = true) /** * Pass the collection to the given callback and then return it. * - * @param callable $callback + * @param callable(TValue): mixed $callback * @return $this */ public function tap(callable $callback) @@ -745,9 +781,9 @@ public function tap(callable $callback) /** * Return only unique items from the collection array. * - * @param string|callable|null $key + * @param (callable(TValue, TKey): bool)|string|null $key * @param bool $strict - * @return static + * @return static */ public function unique($key = null, $strict = false) { @@ -767,8 +803,8 @@ public function unique($key = null, $strict = false) /** * Return only unique items from the collection array using strict comparison. * - * @param string|callable|null $key - * @return static + * @param (callable(TValue, TKey): bool)|string|null $key + * @return static */ public function uniqueStrict($key = null) { @@ -778,7 +814,7 @@ public function uniqueStrict($key = null) /** * Collect the values into a collection. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function collect() { @@ -788,7 +824,7 @@ public function collect() /** * Get the collection of items as a plain array. * - * @return array + * @return array */ public function toArray() { @@ -800,7 +836,7 @@ public function toArray() /** * Convert the object into something JSON serializable. * - * @return array + * @return array */ #[\ReturnTypeWillChange] public function jsonSerialize() diff --git a/src/Illuminate/Collections/helpers.php b/src/Illuminate/Collections/helpers.php index 5138b2cd1a12..45fc6d40510d 100644 --- a/src/Illuminate/Collections/helpers.php +++ b/src/Illuminate/Collections/helpers.php @@ -7,8 +7,11 @@ /** * Create a collection from the given value. * - * @param mixed $value - * @return \Illuminate\Support\Collection + * @template TKey of array-key + * @template TValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable|null $value + * @return \Illuminate\Support\Collection */ function collect($value = null) { diff --git a/src/Illuminate/Conditionable/Traits/Conditionable.php b/src/Illuminate/Conditionable/Traits/Conditionable.php index 924051fb7260..aa77df52759b 100644 --- a/src/Illuminate/Conditionable/Traits/Conditionable.php +++ b/src/Illuminate/Conditionable/Traits/Conditionable.php @@ -10,10 +10,12 @@ trait Conditionable /** * Apply the callback if the given "value" is (or resolves to) truthy. * - * @param mixed $value - * @param callable|null $callback - * @param callable|null $default - * @return $this|mixed + * @template TWhenReturnType + * + * @param bool $value + * @param (callable($this): TWhenReturnType)|null $callback + * @param (callable($this): TWhenReturnType)|null $default + * @return $this|TWhenReturnType */ public function when($value, callable $callback = null, callable $default = null) { @@ -35,10 +37,12 @@ public function when($value, callable $callback = null, callable $default = null /** * Apply the callback if the given "value" is (or resolves to) falsy. * - * @param mixed $value - * @param callable|null $callback - * @param callable|null $default - * @return $this|mixed + * @template TUnlessReturnType + * + * @param bool $value + * @param (callable($this): TUnlessReturnType) $callback + * @param (callable($this): TUnlessReturnType)|null $default + * @return $this|TUnlessReturnType */ public function unless($value, callable $callback = null, callable $default = null) { diff --git a/src/Illuminate/Contracts/Queue/QueueableCollection.php b/src/Illuminate/Contracts/Queue/QueueableCollection.php index 7f1ea19c5436..750d10d4b088 100644 --- a/src/Illuminate/Contracts/Queue/QueueableCollection.php +++ b/src/Illuminate/Contracts/Queue/QueueableCollection.php @@ -14,14 +14,14 @@ public function getQueueableClass(); /** * Get the identifiers for all of the entities. * - * @return array + * @return array */ public function getQueueableIds(); /** * Get the relationships of the entities being queued. * - * @return array + * @return array */ public function getQueueableRelations(); diff --git a/src/Illuminate/Contracts/Support/Arrayable.php b/src/Illuminate/Contracts/Support/Arrayable.php index 5ad93b70bd3b..3194bd1163e0 100755 --- a/src/Illuminate/Contracts/Support/Arrayable.php +++ b/src/Illuminate/Contracts/Support/Arrayable.php @@ -2,12 +2,16 @@ namespace Illuminate\Contracts\Support; +/** + * @template TKey of array-key + * @template TValue + */ interface Arrayable { /** * Get the instance as an array. * - * @return array + * @return array */ public function toArray(); } diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index ff9b2747fe3e..be2fcc60c688 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -10,14 +10,22 @@ use Illuminate\Support\Str; use LogicException; +/** + * @template TKey of array-key + * @template TModel of \Illuminate\Database\Eloquent\Model + * + * @extends \Illuminate\Support\Collection + */ class Collection extends BaseCollection implements QueueableCollection { /** * Find a model in the collection by key. * + * @template TFindDefault + * * @param mixed $key - * @param mixed $default - * @return \Illuminate\Database\Eloquent\Model|static|null + * @param TFindDefault $default + * @return static|TModel|TFindDefault */ public function find($key, $default = null) { @@ -45,7 +53,7 @@ public function find($key, $default = null) /** * Load a set of relationships onto the collection. * - * @param array|string $relations + * @param array|string $relations * @return $this */ public function load($relations) @@ -66,9 +74,9 @@ public function load($relations) /** * Load a set of aggregations over relationship's column onto the collection. * - * @param array|string $relations + * @param array|string $relations * @param string $column - * @param string $function + * @param string|null $function * @return $this */ public function loadAggregate($relations, $column, $function = null) @@ -101,7 +109,7 @@ public function loadAggregate($relations, $column, $function = null) /** * Load a set of relationship counts onto the collection. * - * @param array|string $relations + * @param array|string $relations * @return $this */ public function loadCount($relations) @@ -112,7 +120,7 @@ public function loadCount($relations) /** * Load a set of relationship's max column values onto the collection. * - * @param array|string $relations + * @param array|string $relations * @param string $column * @return $this */ @@ -124,7 +132,7 @@ public function loadMax($relations, $column) /** * Load a set of relationship's min column values onto the collection. * - * @param array|string $relations + * @param array|string $relations * @param string $column * @return $this */ @@ -136,7 +144,7 @@ public function loadMin($relations, $column) /** * Load a set of relationship's column summations onto the collection. * - * @param array|string $relations + * @param array|string $relations * @param string $column * @return $this */ @@ -148,7 +156,7 @@ public function loadSum($relations, $column) /** * Load a set of relationship's average column values onto the collection. * - * @param array|string $relations + * @param array|string $relations * @param string $column * @return $this */ @@ -160,7 +168,7 @@ public function loadAvg($relations, $column) /** * Load a set of related existences onto the collection. * - * @param array|string $relations + * @param array|string $relations * @return $this */ public function loadExists($relations) @@ -171,7 +179,7 @@ public function loadExists($relations) /** * Load a set of relationships onto the collection if they are not already eager loaded. * - * @param array|string $relations + * @param array|string $relations * @return $this */ public function loadMissing($relations) @@ -245,7 +253,7 @@ protected function loadMissingRelation(self $models, array $path) * Load a set of relationships onto the mixed relationship collection. * * @param string $relation - * @param array $relations + * @param array $relations * @return $this */ public function loadMorph($relation, $relations) @@ -266,7 +274,7 @@ public function loadMorph($relation, $relations) * Load a set of relationship counts onto the mixed relationship collection. * * @param string $relation - * @param array $relations + * @param array $relations * @return $this */ public function loadMorphCount($relation, $relations) @@ -286,7 +294,7 @@ public function loadMorphCount($relation, $relations) /** * Determine if a key exists in the collection. * - * @param mixed $key + * @param (callable(TModel, TKey): bool)|TModel|string $key * @param mixed $operator * @param mixed $value * @return bool @@ -311,7 +319,7 @@ public function contains($key, $operator = null, $value = null) /** * Get the array of primary keys. * - * @return array + * @return array */ public function modelKeys() { @@ -323,8 +331,8 @@ public function modelKeys() /** * Merge the collection with the given items. * - * @param \ArrayAccess|array $items - * @return static + * @param iterable $items + * @return static */ public function merge($items) { @@ -340,8 +348,10 @@ public function merge($items) /** * Run a map over each of the items. * - * @param callable $callback - * @return \Illuminate\Support\Collection|static + * @template TMapValue + * + * @param callable(TModel, TKey): TMapValue $callback + * @return \Illuminate\Support\Collection|static */ public function map(callable $callback) { @@ -357,8 +367,11 @@ public function map(callable $callback) * * The callback should return an associative array with a single key / value pair. * - * @param callable $callback - * @return \Illuminate\Support\Collection|static + * @template TMapWithKeysKey of array-key + * @template TMapWithKeysValue + * + * @param callable(TModel, TKey): array $callback + * @return \Illuminate\Support\Collection|static */ public function mapWithKeys(callable $callback) { @@ -372,8 +385,8 @@ public function mapWithKeys(callable $callback) /** * Reload a fresh model instance from the database for all the entities. * - * @param array|string $with - * @return static + * @param array|string $with + * @return static */ public function fresh($with = []) { @@ -400,8 +413,8 @@ public function fresh($with = []) /** * Diff the collection with the given items. * - * @param \ArrayAccess|array $items - * @return static + * @param iterable $items + * @return static */ public function diff($items) { @@ -421,8 +434,8 @@ public function diff($items) /** * Intersect the collection with the given items. * - * @param \ArrayAccess|array $items - * @return static + * @param iterable $items + * @return static */ public function intersect($items) { @@ -446,9 +459,9 @@ public function intersect($items) /** * Return only unique items from the collection. * - * @param string|callable|null $key + * @param (callable(TModel, TKey): bool)|string|null $key * @param bool $strict - * @return static + * @return static */ public function unique($key = null, $strict = false) { @@ -462,8 +475,8 @@ public function unique($key = null, $strict = false) /** * Returns only the models from the collection with the specified keys. * - * @param mixed $keys - * @return static + * @param array|null $keys + * @return static */ public function only($keys) { @@ -479,8 +492,8 @@ public function only($keys) /** * Returns all models in the collection except the models with specified keys. * - * @param mixed $keys - * @return static + * @param array|null $keys + * @return static */ public function except($keys) { @@ -492,7 +505,7 @@ public function except($keys) /** * Make the given, typically visible, attributes hidden across the entire collection. * - * @param array|string $attributes + * @param array|string $attributes * @return $this */ public function makeHidden($attributes) @@ -503,7 +516,7 @@ public function makeHidden($attributes) /** * Make the given, typically hidden, attributes visible across the entire collection. * - * @param array|string $attributes + * @param array|string $attributes * @return $this */ public function makeVisible($attributes) @@ -514,7 +527,7 @@ public function makeVisible($attributes) /** * Append an attribute across the entire collection. * - * @param array|string $attributes + * @param array|string $attributes * @return $this */ public function append($attributes) @@ -525,8 +538,8 @@ public function append($attributes) /** * Get a dictionary keyed by primary keys. * - * @param \ArrayAccess|array|null $items - * @return array + * @param iterable|null $items + * @return array */ public function getDictionary($items = null) { @@ -548,9 +561,9 @@ public function getDictionary($items = null) /** * Get an array with the values of a given key. * - * @param string|array $value + * @param string|array $value * @param string|null $key - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function pluck($value, $key = null) { @@ -560,7 +573,7 @@ public function pluck($value, $key = null) /** * Get the keys of the collection items. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function keys() { @@ -570,8 +583,10 @@ public function keys() /** * Zip the collection together with one or more arrays. * - * @param mixed ...$items - * @return \Illuminate\Support\Collection + * @template TZipValue + * + * @param \Illuminate\Contracts\Support\Arrayable|iterable ...$items + * @return \Illuminate\Support\Collection> */ public function zip($items) { @@ -581,7 +596,7 @@ public function zip($items) /** * Collapse the collection of items into a single array. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function collapse() { @@ -592,7 +607,7 @@ public function collapse() * Get a flattened array of the items in the collection. * * @param int $depth - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function flatten($depth = INF) { @@ -602,7 +617,7 @@ public function flatten($depth = INF) /** * Flip the items in the collection. * - * @return \Illuminate\Support\Collection + * @return \Illuminate\Support\Collection */ public function flip() { @@ -612,9 +627,11 @@ public function flip() /** * Pad collection to the specified length with a value. * + * @template TPadValue + * * @param int $size - * @param mixed $value - * @return \Illuminate\Support\Collection + * @param TPadValue $value + * @return \Illuminate\Support\Collection */ public function pad($size, $value) { @@ -625,7 +642,7 @@ public function pad($size, $value) * Get the comparison function to detect duplicates. * * @param bool $strict - * @return \Closure + * @return callable(TValue, TValue): bool */ protected function duplicateComparator($strict) { @@ -661,7 +678,7 @@ public function getQueueableClass() /** * Get the identifiers for all of the entities. * - * @return array + * @return array */ public function getQueueableIds() { @@ -677,7 +694,7 @@ public function getQueueableIds() /** * Get the relationships of the entities being queued. * - * @return array + * @return array */ public function getQueueableRelations() { diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index 2222ffe1a46e..8fee029b5357 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -526,7 +526,7 @@ public static function onWriteConnection() * Get all of the models from the database. * * @param array|mixed $columns - * @return \Illuminate\Database\Eloquent\Collection|static[] + * @return \Illuminate\Database\Eloquent\Collection */ public static function all($columns = ['*']) { diff --git a/types/Database/Eloquent/Collection.php b/types/Database/Eloquent/Collection.php new file mode 100644 index 000000000000..f1b3527005ad --- /dev/null +++ b/types/Database/Eloquent/Collection.php @@ -0,0 +1,186 @@ +', $collection); + +assertType('Illuminate\Database\Eloquent\Collection|User|null', $collection->find(1)); +assertType('Illuminate\Database\Eloquent\Collection|string|User', $collection->find(1, 'string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->load('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->load(['string'])); +assertType('Illuminate\Database\Eloquent\Collection', $collection->load(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAggregate('string', 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAggregate(['string'], 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAggregate(['string'], 'string', 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAggregate(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}], 'string', 'string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadCount('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadCount(['string'])); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadCount(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMax('string', 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMax(['string'], 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMax(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}], 'string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMin('string', 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMin(['string'], 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMin(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}], 'string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadSum('string', 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadSum(['string'], 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadSum(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}], 'string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAvg('string', 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAvg(['string'], 'string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadAvg(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}], 'string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadExists('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadExists(['string'])); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadExists(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMissing('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMissing(['string'])); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMissing(['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMorph('string', ['string'])); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMorph('string', ['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMorphCount('string', ['string'])); +assertType('Illuminate\Database\Eloquent\Collection', $collection->loadMorphCount('string', ['string' => function ($query) { + // assertType('\Illuminate\Database\Query\Builder', $query); +}])); + +assertType('bool', $collection->contains(function ($user) { + assertType('User', $user); + + return true; +})); +assertType('bool', $collection->contains('string', '=', 'string')); + +assertType('array', $collection->modelKeys()); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->merge($collection)); +assertType('Illuminate\Database\Eloquent\Collection', $collection->merge([new User])); + +assertType( + 'Illuminate\Support\Collection', + $collection->map(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return new User; + }) +); + +assertType( + 'Illuminate\Support\Collection', + $collection->mapWithKeys(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return [new User]; + }) +); +assertType( + 'Illuminate\Support\Collection', + $collection->mapWithKeys(function ($user, $int) { + return ['string' => new User]; + }) +); + +assertType( + 'Illuminate\Database\Eloquent\Collection', + $collection->fresh() +); +assertType( + 'Illuminate\Database\Eloquent\Collection', + $collection->fresh('string') +); +assertType( + 'Illuminate\Database\Eloquent\Collection', + $collection->fresh(['string']) +); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->diff($collection)); +assertType('Illuminate\Database\Eloquent\Collection', $collection->diff([new User])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->intersect($collection)); +assertType('Illuminate\Database\Eloquent\Collection', $collection->intersect([new User])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->unique()); +assertType('Illuminate\Database\Eloquent\Collection', $collection->unique(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); +assertType('Illuminate\Database\Eloquent\Collection', $collection->unique('string')); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->only(null)); +assertType('Illuminate\Database\Eloquent\Collection', $collection->only(['string'])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->except(null)); +assertType('Illuminate\Database\Eloquent\Collection', $collection->except(['string'])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->makeHidden('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->makeHidden(['string'])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->makeVisible('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->makeVisible(['string'])); + +assertType('Illuminate\Database\Eloquent\Collection', $collection->append('string')); +assertType('Illuminate\Database\Eloquent\Collection', $collection->append(['string'])); + +assertType('array', $collection->getDictionary()); +assertType('array', $collection->getDictionary($collection)); +assertType('array', $collection->getDictionary([new User])); + +assertType('Illuminate\Support\Collection', $collection->pluck('string')); +assertType('Illuminate\Support\Collection', $collection->pluck(['string'])); + +assertType('Illuminate\Support\Collection', $collection->keys()); + +assertType('Illuminate\Support\Collection>', $collection->zip([1])); +assertType('Illuminate\Support\Collection>', $collection->zip(['string'])); + +assertType('Illuminate\Support\Collection', $collection->collapse()); + +assertType('Illuminate\Support\Collection', $collection->flatten()); +assertType('Illuminate\Support\Collection', $collection->flatten(4)); + +assertType('Illuminate\Support\Collection', $collection->flip()); + +assertType('Illuminate\Support\Collection', $collection->pad(2, 0)); +assertType('Illuminate\Support\Collection', $collection->pad(2, 'string')); + +assertType('array', $collection->getQueueableIds()); + +assertType('array', $collection->getQueueableRelations()); diff --git a/types/Support/Collection.php b/types/Support/Collection.php new file mode 100644 index 000000000000..c11e5f40c6b0 --- /dev/null +++ b/types/Support/Collection.php @@ -0,0 +1,861 @@ + $arrayable */ +$arrayable = []; +/** @var iterable $iterable */ +$iterable = []; +/** @var Traversable $traversable */ +$traversable = []; + +assertType('Illuminate\Support\Collection', $collection); + +assertType('Illuminate\Support\Collection', collect(['string'])); +assertType('Illuminate\Support\Collection', collect(['string' => new User])); +assertType('Illuminate\Support\Collection', collect($arrayable)); +assertType('Illuminate\Support\Collection', collect($collection)); +assertType('Illuminate\Support\Collection', collect($collection)); +assertType('Illuminate\Support\Collection', collect($iterable)); +assertType('Illuminate\Support\Collection', collect($traversable)); + +assertType('Illuminate\Support\Collection', $collection::make(['string'])); +assertType('Illuminate\Support\Collection', $collection::make(['string' => new User])); +assertType('Illuminate\Support\Collection', $collection::make($arrayable)); +assertType('Illuminate\Support\Collection', $collection::make($collection)); +assertType('Illuminate\Support\Collection', $collection::make($collection)); +assertType('Illuminate\Support\Collection', $collection::make($iterable)); +assertType('Illuminate\Support\Collection', $collection::make($traversable)); + +assertType('Illuminate\Support\Collection', $collection::times(10, function ($int) { + // assertType('int', $int); + + return new User; +})); + +assertType('Illuminate\Support\Collection', $collection::times(10, function () { + return new User; +})); + +assertType('Illuminate\Support\Collection', $collection->each(function ($user) { + assertType('User', $user); +})); + +assertType('Illuminate\Support\Collection', $collection->range(1, 100)); + +assertType('Illuminate\Support\Collection', $collection->wrap(['string'])); +assertType('Illuminate\Support\Collection', $collection->wrap(['string' => new User])); + +assertType('array', $collection->unwrap(['string'])); +assertType('array', $collection->unwrap( + $collection +)); + +assertType('Illuminate\Support\Collection', $collection::empty()); + +assertType('float|int|null', $collection->average()); +assertType('float|int|null', $collection->average('string')); +assertType('float|int|null', $collection->average(function ($user) { + assertType('User', $user); + + return 1; +})); +assertType('float|int|null', $collection->average(function ($user) { + assertType('User', $user); + + return 0.1; +})); + +assertType('float|int|null', $collection->median()); +assertType('float|int|null', $collection->median('string')); +assertType('float|int|null', $collection->median(['string'])); + +assertType('array|null', $collection->mode()); +assertType('array|null', $collection->mode('string')); +assertType('array|null', $collection->mode(['string'])); + +assertType('Illuminate\Support\Collection', $collection->collapse()); + +assertType('bool', $collection->some(function ($user) { + assertType('User', $user); + + return true; +})); +assertType('bool', $collection::make(['string'])->some('string', '=', 'string')); + +assertType('bool', $collection->containsStrict(function ($user) { + assertType('User', $user); + + return true; +})); +assertType('bool', $collection::make(['string'])->containsStrict('string', 'string')); + +assertType('float|int|null', $collection->avg()); +assertType('float|int|null', $collection->avg('string')); +assertType('float|int|null', $collection->avg(function ($user) { + assertType('User', $user); + + return 1; +})); +assertType('float|int|null', $collection->avg(function ($user) { + assertType('User', $user); + + return 0.1; +})); + +assertType('bool', $collection->contains(function ($user) { + assertType('User', $user); + + return true; +})); +assertType('bool', $collection::make(['string'])->contains('string', '=', 'string')); + +assertType('Illuminate\Support\Collection>', $collection->crossJoin($collection::make(['string']))); +assertType('Illuminate\Support\Collection>', $collection->crossJoin([1, 2])); + +assertType('Illuminate\Support\Collection', $collection::make([3, 4])->diff([1, 2])); +assertType('Illuminate\Support\Collection', $collection::make(['string-1'])->diff(['string-2'])); + +assertType('Illuminate\Support\Collection', $collection::make([3, 4])->diffUsing([1, 2], function ($int) { + assertType('int', $int); + + return -1; +})); +assertType('Illuminate\Support\Collection', $collection::make(['string-1'])->diffUsing(['string-2'], function ($string) { + assertType('string', $string); + + return -1; +})); + +assertType('Illuminate\Support\Collection', $collection::make([3, 4])->diffAssoc([1, 2])); +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string'])->diffAssoc(['string' => 'string'])); + +assertType('Illuminate\Support\Collection', $collection::make([3, 4])->diffAssocUsing([1, 2], function ($int) { + assertType('int', $int); + + return -1; +})); +assertType('Illuminate\Support\Collection', $collection::make(['string-1'])->diffAssocUsing(['string-2'], function ($int) { + assertType('int', $int); + + return -1; +})); + +assertType('Illuminate\Support\Collection', $collection::make([3, 4])->diffKeys([1, 2])); +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string'])->diffKeys(['string' => 'string'])); + +assertType('Illuminate\Support\Collection', $collection::make([3, 4])->diffKeysUsing([1, 2], function ($int) { + assertType('int', $int); + + return -1; +})); +assertType('Illuminate\Support\Collection', $collection::make(['string-1'])->diffKeysUsing(['string-2'], function ($int) { + assertType('int', $int); + + return -1; +})); + +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string']) + ->duplicates()); +assertType('Illuminate\Support\Collection', $collection->duplicates('name', true)); +assertType('Illuminate\Support\Collection', $collection::make([3, 'string']) + ->duplicates(function ($intOrString) { + assertType('int|string', $intOrString); + + return true; + })); + +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string']) + ->duplicatesStrict()); +assertType('Illuminate\Support\Collection', $collection->duplicatesStrict('name')); +assertType('Illuminate\Support\Collection', $collection::make([3, 'string']) + ->duplicatesStrict(function ($intOrString) { + assertType('int|string', $intOrString); + + return true; + })); + +assertType('Illuminate\Support\Collection', $collection->each(function ($user) { + assertType('User', $user); + + return null; +})); +assertType('Illuminate\Support\Collection', $collection->each(function ($user) { + assertType('User', $user); +})); + +assertType('Illuminate\Support\Collection', $collection::make([['string']]) + ->eachSpread(function ($int, $string) { + // assertType('int', $int); + // assertType('int', $string); + + return null; + })); +assertType('Illuminate\Support\Collection', $collection::make([[1, 'string']]) + ->eachSpread(function ($int, $string) { + // assertType('int', $int); + // assertType('int', $string); + })); + +assertType('bool', $collection->every(function ($user, $int) { + assertType('int', $int); + assertType('User', $user); + + return true; +})); +assertType('bool', $collection::make(['string'])->every('string', '=', 'string')); + +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string'])->except(['string'])); +assertType('Illuminate\Support\Collection', $collection->except([1])); +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->except($collection->keys()->toArray())); + +assertType('Illuminate\Support\Collection', $collection->filter()); +assertType('Illuminate\Support\Collection', $collection->filter(function ($user) { + assertType('User', $user); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->filter()); +assertType('Illuminate\Support\Collection', $collection->filter(function ($user) { + assertType('User', $user); + + return true; +})); + +assertType('bool|Illuminate\Support\Collection', $collection->when(true, function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); +assertType('Illuminate\Support\Collection|void', $collection->when(true, function ($collection) { + assertType('Illuminate\Support\Collection', $collection); +})); +assertType('Illuminate\Support\Collection|string', $collection->when(true, function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 'string'; +})); + +assertType('bool|Illuminate\Support\Collection', $collection->whenEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); +assertType('Illuminate\Support\Collection|void', $collection->whenEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); +})); +assertType('Illuminate\Support\Collection|string', $collection->whenEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 'string'; +})); + +assertType('bool|Illuminate\Support\Collection', $collection->whenNotEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); +assertType('Illuminate\Support\Collection|void', $collection->whenNotEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); +})); +assertType('Illuminate\Support\Collection|string', $collection->whenNotEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 'string'; +})); + +assertType('bool|Illuminate\Support\Collection', $collection->unless(true, function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); +assertType('Illuminate\Support\Collection|void', $collection->unless(true, function ($collection) { + assertType('Illuminate\Support\Collection', $collection); +})); +assertType('Illuminate\Support\Collection|string', $collection->unless(true, function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 'string'; +})); + +assertType('bool|Illuminate\Support\Collection', $collection->unlessEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); +assertType('Illuminate\Support\Collection|void', $collection->unlessEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); +})); +assertType('Illuminate\Support\Collection|string', $collection->unlessEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 'string'; +})); + +assertType('bool|Illuminate\Support\Collection', $collection->unlessNotEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); +assertType('Illuminate\Support\Collection|void', $collection->unlessNotEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); +})); +assertType('Illuminate\Support\Collection|string', $collection->unlessNotEmpty(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 'string'; +})); + +assertType("Illuminate\Support\Collection string)>", $collection::make([['string' => 'string']]) + ->where('string')); +assertType("Illuminate\Support\Collection string)>", $collection::make([['string' => 'string']]) + ->where('string', '=', 'string')); +assertType("Illuminate\Support\Collection string)>", $collection::make([['string' => 'string']]) + ->where('string', 'string')); + +assertType('Illuminate\Support\Collection', $collection->whereNull()); +assertType('Illuminate\Support\Collection', $collection->whereNull('foo')); + +assertType('Illuminate\Support\Collection', $collection->whereNotNull()); +assertType('Illuminate\Support\Collection', $collection->whereNotNull('foo')); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereStrict('string', 2)); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereIn('string', [2])); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereInStrict('string', [2])); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereBetween('string', [1, 3])); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereNotBetween('string', [1, 3])); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereNotIn('string', [2])); + +assertType("Illuminate\Support\Collection int)>", $collection::make([['string' => 2]]) + ->whereNotInStrict('string', [2])); + +assertType('Illuminate\Support\Collection', $collection::make([new User, 1]) + ->whereInstanceOf(User::class)); + +assertType('Illuminate\Support\Collection', $collection::make([new User, 1]) + ->whereInstanceOf([User::class, User::class])); + +assertType('User|null', $collection->first()); +assertType('User|null', $collection->first(function ($user) { + assertType('User', $user); + + return true; +})); +assertType('string|User', $collection->first(function ($user) { + assertType('User', $user); + + return false; +}, 'string')); + +assertType('Illuminate\Support\Collection', $collection->flatten()); +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string'])->flatten(4)); + +assertType('User|null', $collection->firstWhere('string', 'string')); +assertType('User|null', $collection->firstWhere('string', 'string', 'string')); + +assertType('Illuminate\Support\Collection', $collection::make(['string'])->flip()); + +assertType('Illuminate\Support\Collection<(int|string), array>', $collection->groupBy('name')); +assertType('Illuminate\Support\Collection<(int|string), array>', $collection->groupBy('name', true)); +assertType('Illuminate\Support\Collection<(int|string), array>', $collection->groupBy(function ($user, $int) { + // assertType('User', $user); + // assertType('int', $int); + + return 'foo'; +})); +assertType('Illuminate\Support\Collection<(int|string), array>', $collection->groupBy(function ($user) { + return 'foo'; +})); + +assertType('Illuminate\Support\Collection<(int|string), array>', $collection->keyBy('name')); +assertType('Illuminate\Support\Collection<(int|string), array>', $collection->keyBy(function ($user, $int) { + // assertType('User', $user); + // assertType('int', $int); + + return 'foo'; +})); + +assertType('bool', $collection->has(0)); +assertType('bool', $collection->has([0, 1])); + +assertType('Illuminate\Support\Collection', $collection->intersect([new User])); + +assertType('Illuminate\Support\Collection', $collection->intersectByKeys([new User])); + +assertType('Illuminate\Support\Collection', $collection->keys()); + +assertType('User|null', $collection->last()); +assertType('User|null', $collection->last(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); +assertType('string|User', $collection->last(function () { + return true; +}, 'string')); + +assertType('Illuminate\Support\Collection', $collection->map(function () { + return 1; +})); +assertType('Illuminate\Support\Collection', $collection->map(function () { + return 'string'; +})); + +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->map(function ($string, $int) { + assertType('string', $string); + assertType('int', $int); + + return (string) $string; + })); + +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->mapSpread(function () { + return 'string'; + })); + +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->mapSpread(function () { + return 1; + })); + +assertType('Illuminate\Support\Collection>', $collection::make(['string', 'string']) + ->mapToDictionary(function ($stringValue, $stringKey) { + assertType('string', $stringValue); + assertType('int', $stringKey); + + return ['string' => 1]; + })); + +assertType('Illuminate\Support\Collection>', $collection::make(['string', 'string']) + ->mapToGroups(function ($stringValue, $stringKey) { + assertType('string', $stringValue); + assertType('int', $stringKey); + + return ['string' => 1]; + })); + +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->mapWithKeys(function ($string, $int) { + assertType('string', $string); + assertType('int', $int); + + return ['string' => 1]; + })); + +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->flatMap(function ($string, $int) { + assertType('string', $string); + assertType('int', $int); + + return 1; + })); + +assertType('Illuminate\Support\Collection', $collection->mapInto(User::class)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->merge([2])); +assertType('Illuminate\Support\Collection', $collection->make(['string'])->merge(['string'])); + +assertType('Illuminate\Support\Collection>', $collection->make([1])->mergeRecursive([2])); +assertType('Illuminate\Support\Collection>', $collection->make(['string'])->mergeRecursive(['string'])); + +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->combine([2])); +assertType('Illuminate\Support\Collection', $collection->make([1])->combine([1])); + +assertType('Illuminate\Support\Collection', $collection->make([1])->union([1])); +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->union(['string' => 'string'])); + +assertType('int', $collection->make([1])->min()); +assertType('int', $collection->make([1])->min('string')); +assertType('int', $collection->make([1])->min(function ($int) { + assertType('int', $int); + + return 1; +})); + +assertType('int', $collection->make([1])->max()); +assertType('int', $collection->make([1])->max('string')); +assertType('int', $collection->make([1])->max(function ($int) { + assertType('int', $int); + + return 1; +})); + +assertType('Illuminate\Support\Collection', $collection->nth(1, 2)); + +assertType('Illuminate\Support\Collection', $collection::make(['string' => 'string'])->only(['string'])); +assertType('Illuminate\Support\Collection', $collection->only([1])); +assertType('Illuminate\Support\Collection', $collection::make(['string']) + ->only($collection->keys()->toArray())); + +assertType('Illuminate\Support\Collection', $collection->forPage(1, 2)); + +assertType('array>', $collection->partition(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); +assertType('array>', $collection::make(['string'])->partition('string', '=', 'string')); +assertType('array>', $collection::make(['string'])->partition('string', 'string')); +assertType('array>', $collection::make(['string'])->partition('string', )); + +assertType('Illuminate\Support\Collection', $collection->make([1])->concat([2])); +assertType('Illuminate\Support\Collection', $collection->make(['string'])->concat(['string'])); + +assertType('Illuminate\Support\Collection|int', $collection->make([1])->random(2)); +assertType('Illuminate\Support\Collection|string', $collection->make(['string'])->random()); + +assertType('int', $collection + ->reduce(function ($null, $user) { + assertType('User', $user); + assertType('int|null', $null); + + return 1; + })); +assertType('int', $collection + ->reduce(function ($int, $user) { + assertType('User', $user); + assertType('int', $int); + + return 1; + }, 0)); + +assertType('int', $collection + ->reduceWithKeys(function ($null, $user) { + assertType('User', $user); + assertType('int|null', $null); + + return 1; + })); +assertType('int', $collection + ->reduceWithKeys(function ($int, $user) { + assertType('User', $user); + assertType('int', $int); + + return 1; + }, 0)); + +assertType('Illuminate\Support\Collection', $collection::make([1])->replace([1])); +assertType('Illuminate\Support\Collection', $collection->replace([new User])); + +assertType('Illuminate\Support\Collection', $collection::make([1])->replaceRecursive([1])); +assertType('Illuminate\Support\Collection', $collection->replaceRecursive([new User])); + +assertType('Illuminate\Support\Collection', $collection->reverse()); + +// assertType('int|bool', $collection->make([1])->search(2)); +// assertType('string|bool', $collection->make(['string' => 'string'])->search('string')); +// assertType('int|bool', $collection->search(function ($user, $int) { +// assertType('User', $user); +// assertType('int', $int); +// +// return true; +// })); + +assertType('Illuminate\Support\Collection', $collection->make([1])->shuffle()); +assertType('Illuminate\Support\Collection', $collection->shuffle()); + +assertType('Illuminate\Support\Collection', $collection->make([1])->skip(1)); +assertType('Illuminate\Support\Collection', $collection->skip(1)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->skipUntil(1)); +assertType('Illuminate\Support\Collection', $collection->skipUntil(new User)); +assertType('Illuminate\Support\Collection', $collection->skipUntil(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->make([1])->skipWhile(1)); +assertType('Illuminate\Support\Collection', $collection->skipWhile(new User)); +assertType('Illuminate\Support\Collection', $collection->skipWhile(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->make([1])->slice(1)); +assertType('Illuminate\Support\Collection', $collection->slice(1, 2)); + +assertType('Illuminate\Support\Collection>', $collection->split(3)); +assertType('Illuminate\Support\Collection>', $collection->make([1])->split(3)); + +assertType('string', $collection->make(['string' => 'string'])->sole('string', 'string')); +assertType('string', $collection->make(['string' => 'string'])->sole('string', '=', 'string')); +assertType('User', $collection->sole(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); + +assertType('Illuminate\Support\Collection>', $collection::make(['string'])->chunk(1)); +assertType('Illuminate\Support\Collection>', $collection->chunk(2)); + +assertType('Illuminate\Support\Collection>', $collection->chunkWhile(function ($user, $int, $collection) { + assertType('User', $user); + assertType('int', $int); + assertType('Illuminate\Support\Collection', $collection); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->sort(function ($userA, $userB) { + assertType('User', $userA); + assertType('User', $userB); + + return true; +})); +assertType('Illuminate\Support\Collection', $collection->sort()); + +assertType('Illuminate\Support\Collection', $collection->sortDesc()); +assertType('Illuminate\Support\Collection', $collection->sortDesc(2)); + +assertType('Illuminate\Support\Collection', $collection->sortBy(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return 1; +})); +assertType('Illuminate\Support\Collection', $collection->sortBy('string')); +assertType('Illuminate\Support\Collection', $collection->sortBy('string', 1, false)); + +assertType('Illuminate\Support\Collection', $collection->sortByDesc(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return 1; +})); + +assertType('Illuminate\Support\Collection', $collection->make([1])->sortKeys()); +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->sortKeys(1, true)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->sortKeysDesc()); +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->sortKeysDesc(1)); + +assertType('mixed', $collection->make([1])->sum('string')); +assertType('mixed', $collection->make(['string'])->sum(function ($string) { + assertType('string', $string); + + return 1; +})); + +assertType('Illuminate\Support\Collection', $collection->make([1])->take(1)); +assertType('Illuminate\Support\Collection', $collection->take(1)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->takeUntil(1)); +assertType('Illuminate\Support\Collection', $collection->takeUntil(new User)); +assertType('Illuminate\Support\Collection', $collection->takeUntil(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->make([1])->takeWhile(1)); +assertType('Illuminate\Support\Collection', $collection->takeWhile(new User)); +assertType('Illuminate\Support\Collection', $collection->takeWhile(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->tap(function ($user) { + assertType('User', $user); +})); + +assertType('Illuminate\Support\Collection', $collection->pipe(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return collect([1]); +})); +assertType('int', $collection->make([1])->pipe(function ($collection) { + assertType('Illuminate\Support\Collection', $collection); + + return 1; +})); + +assertType('mixed', $collection->pipeInto(User::class)); + +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->pluck('string')); +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->pluck('string', 'string')); + +assertType('Illuminate\Support\Collection', $collection->reject()); +assertType('Illuminate\Support\Collection', $collection->reject(function ($user) { + assertType('User', $user); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->unique()); +assertType('Illuminate\Support\Collection', $collection->unique(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->unique(function ($stringA, $stringB) { + assertType('string', $stringA); + assertType('string', $stringA); + + return false; +}, true)); + +assertType('Illuminate\Support\Collection', $collection->uniqueStrict()); +assertType('Illuminate\Support\Collection', $collection->uniqueStrict(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return true; +})); + +assertType('Illuminate\Support\Collection', $collection->values()); +assertType('Illuminate\Support\Collection', $collection::make(['string', 'string'])->values()); +assertType('Illuminate\Support\Collection', $collection::make(['string', 1])->values()); + +assertType('Illuminate\Support\Collection', $collection->make([1])->pad(2, 0)); +assertType('Illuminate\Support\Collection', $collection->make([1])->pad(2, 'string')); +assertType('Illuminate\Support\Collection', $collection->pad(2, 0)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->countBy()); +assertType('Illuminate\Support\Collection', $collection->make(['string' => 'string'])->countBy('string')); +assertType('Illuminate\Support\Collection', $collection->make(['string'])->countBy(function ($string, $int) { + assertType('string', $string); + assertType('int', $int); + + return false; +})); + +assertType('Illuminate\Support\Collection>', $collection->zip([1])); +assertType('Illuminate\Support\Collection>', $collection->zip(['string'])); +assertType('Illuminate\Support\Collection>', $collection::make(['string' => 'string'])->zip(['string'])); + +assertType('Illuminate\Support\Collection', $collection->collect()); +assertType('Illuminate\Support\Collection', $collection->make([1])->collect()); + +assertType('Illuminate\Support\Collection', $collection->make([1])->push(2)); + +assertType('array', $collection->all()); + +assertType('User|null', $collection->get(0)); +assertType('string|User', $collection->get(0, 'string')); + +assertType('Illuminate\Support\Collection', $collection->forget(1)); +assertType('Illuminate\Support\Collection', $collection->forget([1, 2])); + +assertType('Illuminate\Support\Collection|User|null', $collection->pop(1)); +assertType('Illuminate\Support\Collection|string|null', $collection::make([ + 'string-key-1' => 'string-value-1', + 'string-key-2' => 'string-value-2', +])->pop(2)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->prepend(2)); +assertType('Illuminate\Support\Collection', $collection->prepend(new User, 2)); + +assertType('Illuminate\Support\Collection', $collection->make([1])->push(2)); +assertType('Illuminate\Support\Collection', $collection->push(new User, new User)); + +assertType('User|null', $collection->pull(1)); +assertType('string|User', $collection->pull(1, 'string')); + +assertType('Illuminate\Support\Collection', $collection->put(1, new User)); +assertType('Illuminate\Support\Collection', $collection::make([ + 'string-key-1' => 'string-value-1', +])->put('string-key-2', 'string-value-2')); + +assertType('Illuminate\Support\Collection|User|null', $collection->shift(1)); +assertType('Illuminate\Support\Collection|string|null', $collection::make([ + 'string-key-1' => 'string-value-1', + 'string-key-2' => 'string-value-2', +])->shift(2)); + +assertType( + 'Illuminate\Support\Collection>', + $collection->sliding(2) +); + +assertType( + 'Illuminate\Support\Collection>', + $collection::make(['string' => 'string'])->sliding(2, 1) +); + +assertType( + 'Illuminate\Support\Collection>', + $collection->splitIn(2) +); + +assertType( + 'Illuminate\Support\Collection>', + $collection::make(['string' => 'string'])->splitIn(1) +); + +assertType('Illuminate\Support\Collection', $collection->splice(1)); +assertType('Illuminate\Support\Collection', $collection->splice(1, 1, [new User])); + +assertType('Illuminate\Support\Collection', $collection->transform(function ($user, $int) { + assertType('User', $user); + assertType('int', $int); + + return new User; +})); + +assertType('Illuminate\Support\Collection', $collection->add(new User)); + +/** + * @template TKey of array-key + * @template TValue + * + * @extends \Illuminate\Support\Collection + */ +class CustomCollection extends Collection +{ +} + +// assertType('CustomCollection', CustomCollection::make([new User])); +assertType('Illuminate\Support\Collection', CustomCollection::make([new User])->toBase()); + +assertType('bool', $collection->offsetExists(0)); +assertType('bool', isset($collection[0])); + +$collection->offsetSet(0, new User); +$collection->offsetSet(null, new User); +assertType('User', $collection[0] = new User); + +$collection->offsetUnset(0); +unset($collection[0]); + +assertType('array', $collection->toArray()); +assertType('array', collect(['string' => 'string'])->toArray()); +assertType('array', collect([1, 2])->toArray()); + +assertType('ArrayIterator', $collection->getIterator()); +foreach ($collection as $int => $user) { + assertType('int', $int); + assertType('User', $user); +}