1+ <?php
2+
3+ namespace AssertThis ;
4+
5+ use RuntimeException ;
6+
7+ use function PHPStan \Testing \assertType ;
8+
9+ /**
10+ * @template TOk
11+ * @template TErr
12+ */
13+ interface Result {
14+ /**
15+ * @phpstan-assert-if-true Ok<TOk> $this
16+ * @phpstan-assert-if-false Err<TErr> $this
17+ */
18+ public function isOk (): bool ;
19+
20+ /**
21+ * @return TOk|never
22+ */
23+ public function unwrap ();
24+ }
25+
26+ /**
27+ * @template TOk
28+ * @template-implements Result<TOk, never>
29+ */
30+ class Ok implements Result {
31+ public function __construct (private $ value ) {
32+ }
33+
34+ /**
35+ * @return true
36+ */
37+ public function isOk (): bool {
38+ return true ;
39+ }
40+
41+ /**
42+ * @return TOk
43+ */
44+ public function unwrap () {
45+ return $ this ->value ;
46+ }
47+ }
48+
49+ /**
50+ * @template TErr
51+ * @template-implements Result<never, TErr>
52+ */
53+ class Err implements Result {
54+ public function __construct (private $ value ) {
55+ }
56+
57+ /**
58+ * @return false
59+ */
60+ public function isOk (): bool {
61+ return false ;
62+ }
63+
64+ /**
65+ * @return never
66+ */
67+ public function unwrap () {
68+ throw new RuntimeException ('Tried to unwrap() an Err value ' );
69+ }
70+ }
71+
72+ function () {
73+ /** @var Result<int, string> $result */
74+ $ result = new Ok (123 );
75+ assertType ('AssertThis \\Result<int, string> ' , $ result );
76+
77+ if ($ result ->isOk ()) {
78+ assertType ('AssertThis \\Ok<int> ' , $ result );
79+ assertType ('int ' , $ result ->unwrap ());
80+ } else {
81+ assertType ('AssertThis \\Err<string> ' , $ result );
82+ assertType ('never ' , $ result ->unwrap ());
83+ }
84+ };
0 commit comments