Skip to content

Commit

Permalink
feat: conditional return types for Eloquent\Collection::find() (#1419)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebdesign committed Nov 4, 2022
1 parent 42eb41b commit 333e791
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- fix: Eloquent builder `whereRelation()` losing the TModelClass generic type by @mad-briller.
- feat: updated return type of the Validator::safe and FormRequest::safe method by @jdjfisher
- feat: Added stub for the DB::transaction method by @jdjfisher
- feat: conditional return types for `Eloquent\Collection::find()` by @sebdesign
- feat: add support for generic paginators by @erikgaal

## [2.2.0] - 2022-08-31
Expand Down
Expand Up @@ -28,7 +28,7 @@ public function getClass(): string
public function isMethodSupported(MethodReflection $methodReflection): bool
{
if ($methodReflection->getDeclaringClass()->getName() === EloquentCollection::class) {
return false;
return in_array($methodReflection->getName(), ['find']);
}

return in_array($methodReflection->getName(), [
Expand Down
11 changes: 10 additions & 1 deletion stubs/EloquentCollection.stub
Expand Up @@ -13,5 +13,14 @@ use Illuminate\Support\Collection as BaseCollection;
*/
class Collection extends BaseCollection implements QueueableCollection
{
// ..
/**
* Find a model in the collection by key.
*
* @template TFindDefault
*
* @param mixed $key
* @param TFindDefault $default
* @phpstan-return ($key is \Illuminate\Database\Eloquent\Model ? TModel|TFindDefault : ($key is (\Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<mixed>) ? static<TKey, TModel> : TModel|TFindDefault))
*/
public function find($key, $default = null);
}
19 changes: 19 additions & 0 deletions tests/Type/data/collection-generic-static-methods.php
Expand Up @@ -11,13 +11,32 @@
/** @var SupportCollection<string, int> $items */
/** @var App\TransactionCollection<int, Transaction> $customEloquentCollection */
/** @var App\UserCollection $secondCustomEloquentCollection */
/** @var User $user */
assertType('Illuminate\Database\Eloquent\Collection<int, int>', EloquentCollection::range(1, 10));

assertType('Illuminate\Support\Collection<int, mixed>', $collection->collapse());
assertType('Illuminate\Support\Collection<int, mixed>', $items->collapse());

assertType('Illuminate\Database\Eloquent\Collection<int, array<int, App\User|int>>', $collection->crossJoin([1]));

assertType('Illuminate\Database\Eloquent\Collection<int, App\User>', $collection->find($items));
assertType('Illuminate\Database\Eloquent\Collection<int, App\User>', $collection->find([1]));
assertType('App\User|null', $collection->find($user));
assertType('App\User|null', $collection->find(1));
assertType('App\User|bool', $collection->find(1, false));

assertType('App\TransactionCollection<int, App\Transaction>', $customEloquentCollection->find($items));
assertType('App\TransactionCollection<int, App\Transaction>', $customEloquentCollection->find([1]));
assertType('App\Transaction|null', $customEloquentCollection->find($user));
assertType('App\Transaction|null', $customEloquentCollection->find(1));
assertType('App\Transaction|bool', $customEloquentCollection->find(1, false));

assertType('App\UserCollection', $secondCustomEloquentCollection->find($items));
assertType('App\UserCollection', $secondCustomEloquentCollection->find([1]));
assertType('App\User|null', $secondCustomEloquentCollection->find($user));
assertType('App\User|null', $secondCustomEloquentCollection->find(1));
assertType('App\User|bool', $secondCustomEloquentCollection->find(1, false));

assertType('Illuminate\Support\Collection<int, mixed>', $collection->flatten());
assertType('Illuminate\Support\Collection<int, mixed>', $items->flatten());

Expand Down
7 changes: 7 additions & 0 deletions tests/Type/data/collection-stubs.php
Expand Up @@ -9,6 +9,7 @@

/** @var EloquentCollection<int, User> $collection */
/** @var SupportCollection<string, int> $items */
/** @var User $user */
assertType('Illuminate\Database\Eloquent\Collection<int, App\User>', User::all()->each(function (User $user, int $key): void {
}));

Expand All @@ -20,6 +21,12 @@
return (string) $item;
}));

assertType('Illuminate\Database\Eloquent\Collection<int, App\User>', $collection->find($items));
assertType('Illuminate\Database\Eloquent\Collection<int, App\User>', $collection->find([1]));
assertType('App\User|null', $collection->find($user));
assertType('App\User|null', $collection->find(1));
assertType('App\User|bool', $collection->find(1, false));

assertType('Illuminate\Support\Collection<int, mixed>', $collection->pluck('id'));

assertType('Illuminate\Database\Eloquent\Collection<int, App\User>', User::all()->mapInto(User::class));
Expand Down

0 comments on commit 333e791

Please sign in to comment.