Skip to content

Commit

Permalink
improve typings (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
mathroc committed Jul 16, 2023
1 parent d8cffe3 commit deec0f0
Show file tree
Hide file tree
Showing 15 changed files with 178 additions and 105 deletions.
10 changes: 1 addition & 9 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ parameters:
paths:
- src
- tests
checkGenericClassInNonGenericObjectType: false
exceptions:
check:
missingCheckedExceptionInThrows: true
Expand All @@ -20,14 +21,5 @@ parameters:
-
message: "#Method .*::.*\\(\\) throws checked exception RuntimeException but it's missing from the PHPDoc @throws tag.#"
path: tests/Unit/
-
message: '#Enum TH\\Maybe\\Option\\None has PHPDoc @template tag but enums cannot be generic.#'
path: src/Option/None.php
-
message: '#Return type \(iterable<array{T, U}>&TH\\Maybe\\Option\\None\) of method TH\\Maybe\\Option\\None::zip\(\) should be compatible with return type \(TH\\Maybe\\Option<array{mixed, mixed}>\) of method TH\\Maybe\\Option<T>::zip\(\)#'
path: src/Option/None.php
-
message: '#Parameter \#1 \$callback of method TH\\Maybe\\Option<U>::map\(\) expects callable\(U\): array{T, U}, Closure\(U\): array{T, U} given.#'
path: src/Option/Some.php
excludePaths:
- tests/examples.php
7 changes: 6 additions & 1 deletion psalm.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<psalm
errorLevel="8"
errorLevel="5"
resolveFromConfigFile="true"
strictBinaryOperands="true"
checkForThrowsDocblock="true"
Expand Down Expand Up @@ -80,5 +80,10 @@
<directory name="tests/Unit" />
</errorLevel>
</PropertyNotSetInConstructor>
<InvalidArgument>
<errorLevel type="suppress">
<directory name="tests/Unit" />
</errorLevel>
</InvalidArgument>
</issueHandlers>
</psalm>
15 changes: 9 additions & 6 deletions src/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,9 @@ public function unwrap(): mixed;
* self::assertSame(Option\none()->unwrapOr("bike"), "bike");
* ```
*
* @param T $default
* @return T
* @template U
* @param U $default
* @return T|U
*/
public function unwrapOr(mixed $default): mixed;

Expand All @@ -195,8 +196,9 @@ public function unwrapOr(mixed $default): mixed;
* self::assertSame(Option\none()->unwrapOrElse(fn () => 2 * $k), 20);
* ```
*
* @param callable():T $default
* @return T
* @template U
* @param callable():U $default
* @return T|U
*/
public function unwrapOrElse(callable $default): mixed;

Expand Down Expand Up @@ -326,8 +328,9 @@ public function or(Option $right): Option;
* self::assertSame(Option\none()->orElse(nobody(...)), Option\none());
* ```
*
* @param callable():Option<T> $right
* @return Option<T>
* @template U
* @param callable():Option<U> $right
* @return Option<T|U>
* @psalm-assert-if-false Option\None $this
*/
public function orElse(callable $right): Option;
Expand Down
14 changes: 5 additions & 9 deletions src/Option/None.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
use TH\Maybe\Result;

/**
* @template T
* @implements Option<T>
* @implements Option<never>
* @immutable
* @nodoc
*/
Expand Down Expand Up @@ -141,33 +140,30 @@ public function mapOrElse(callable $callback, callable $default): mixed
/**
* @template U
* @param Option<U> $option
* @return Option\None<array{T, U}>
* @return $this
*/
public function zip(Option $option): Option
public function zip(Option $option): self
{
/** @var Option\None<array{T, U}> */
return $this;
}

/**
* @template E
* @param E $err
* @return Result\Err<T, E>
* @return Result\Err<E>
*/
public function okOr(mixed $err): Result\Err
{
/** @var Result\Err<T, E> */
return Result\err($err);
}

/**
* @template E
* @param callable():E $err
* @return Result\Err<T, E>
* @return Result\Err<E>
*/
public function okOrElse(callable $err): Result\Err
{
/** @var Result\Err<T, E> */
return Result\err($err());
}

Expand Down
32 changes: 14 additions & 18 deletions src/Option/Some.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,17 @@ public function unwrap(): mixed
return $this->value;
}

/**
* @return T
*/
public function unwrapOr(mixed $default): mixed
{
return $this->value;
}

/**
* @return T
*/
public function unwrapOrElse(callable $default): mixed
{
return $this->value;
Expand Down Expand Up @@ -104,7 +110,6 @@ public function orElse(callable $right): Option

public function xor(Option $right): Option
{
/** @var Option<T> */
return $right instanceof Option\None
? $this
: Option\none();
Expand All @@ -120,7 +125,6 @@ public function contains(mixed $value, bool $strict = true): bool

public function filter(callable $predicate): Option
{
/** @var Option<T> */
return $predicate($this->value)
? $this
: Option\none();
Expand All @@ -145,47 +149,39 @@ public function mapOrElse(callable $callback, callable $default): mixed
* @template U
* @param Option<U> $option
* @return Option<array{T, U}>
* @psalm-suppress InvalidReturnType,InvalidReturnStatement
*/
public function zip(Option $option): Option
{
/** @var Option<array{T, U}> */
return $option->map($this->zipMap(...));
foreach ($option as $value) {
return Option\some([$this->value, $value]);
}

return Option\none();
}

/**
* @template E
* @param E $err
* @return Result\Ok<T, E>
* @return Result\Ok<T>
*/
public function okOr(mixed $err): Result\Ok
{
/** @var Result\Ok<T, E> */
return Result\ok($this->value);
}

/**
* @template E
* @param callable():E $err
* @return Result\Ok<T, E>
* @return Result\Ok<T>
*/
public function okOrElse(callable $err): Result\Ok
{
/** @var Result\Ok<T, E> */
return Result\ok($this->value);
}

public function getIterator(): \Traversable
{
yield $this->value;
}

/**
* @template U
* @param U $value
* @return array{T, U}
*/
private function zipMap(mixed $value): array
{
return [$this->value, $value];
}
}
14 changes: 8 additions & 6 deletions src/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public function expect(string $message): mixed;
*
* @return T
* @throws \Throwable
* @psalm-assert Result\Ok $this
* @psalm-assert =Result\Ok $this
*/
public function unwrap(): mixed;

Expand All @@ -219,7 +219,7 @@ public function unwrap(): mixed;
*
* @return E
* @throws \RuntimeException
* @psalm-assert Result\Err $this
* @psalm-assert =Result\Err $this
*/
public function unwrapErr(): mixed;

Expand All @@ -240,8 +240,9 @@ public function unwrapErr(): mixed;
* self::assertEq($x->unwrapOr($default), $default);
* ```
*
* @param T $default
* @return T
* @template U
* @param U $default
* @return T|U
*/
public function unwrapOr(mixed $default): mixed;

Expand All @@ -255,8 +256,9 @@ public function unwrapOr(mixed $default): mixed;
* self::assertEq(Result\err("foo")->unwrapOrElse(strlen(...)), 3);
* ```
*
* @param callable(E):T $default
* @return T
* @template U
* @param callable(E):U $default
* @return T|U
*/
public function unwrapOrElse(callable $default): mixed;

Expand Down
35 changes: 17 additions & 18 deletions src/Result/Err.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
use TH\Maybe\Result;

/**
* @template T
* @template E
* @implements Result<T, E>
* @implements Result<never, E>
* @nodoc
*/
class Err implements Result
Expand Down Expand Up @@ -103,8 +102,9 @@ final public function unwrapErr(): mixed
* Extract the contained value in an `Result<T, E>` when it is the `Ok` variant.
* Or `$default` if the `Result` is `Err`.
*
* @param T $default
* @return T
* @template U
* @param U $default
* @return U
*/
final public function unwrapOr(mixed $default): mixed
{
Expand All @@ -113,6 +113,11 @@ final public function unwrapOr(mixed $default): mixed
return $default;
}

/*
* @template U
* @param callable(E):U $default
* @return U
*/
final public function unwrapOrElse(callable $default): mixed
{
$this->used();
Expand All @@ -121,13 +126,11 @@ final public function unwrapOrElse(callable $default): mixed
}

/**
* @return self<T,E>
* @return $this
*/
final public function inspect(callable $callback): self
{
$this->used();

return clone $this;
return $this;
}

/**
Expand All @@ -141,18 +144,18 @@ final public function inspectErr(callable $callback): self
}

/**
* @return self<T,E>
* @return self<E>
*/
final public function and(Result $right): self
{
$this->used();
$right->ok(); // use this result
$right->isOk(); // use this result

return clone $this;
}

/**
* @return self<T,E>
* @return self<E>
*/
final public function andThen(callable $right): self
{
Expand Down Expand Up @@ -197,7 +200,7 @@ final public function containsErr(mixed $value, bool $strict = true): bool
}

/**
* @return self<T,E>
* @return self<E>
*/
final public function map(callable $callback): self
{
Expand All @@ -209,13 +212,13 @@ final public function map(callable $callback): self
/**
* @template F
* @param callable(E):F $callback
* @return Result\Err<T, F>
* @return self<F>
*/
final public function mapErr(callable $callback): self
{
$this->used();

/** @var Result\Err<T, F> */
/** @var self<F> */
return Result\err($callback($this->value));
}

Expand All @@ -226,14 +229,10 @@ final public function mapOr(callable $callback, mixed $default): mixed
return $default;
}

/**
* @return Option\None<E>
*/
final public function ok(): Option\None
{
$this->used();

/** @var Option\None<E> */
return Option\none();
}

Expand Down
Loading

0 comments on commit deec0f0

Please sign in to comment.