@@ -118,6 +118,20 @@ public function testFilterStrictModeKeepsFalsyValues(): void
118118 /**
119119 * Tests that is_int(...) narrows types correctly.
120120 */
121+ public function testFilterWithIsInt (): void
122+ {
123+ /** @var Standard<int, int|string|float> $pipeline */
124+ $ pipeline = take ([1 , 'hello ' , 3.14 , 42 , 'world ' , 2.71 ]);
125+
126+ // After filter(is_int(...)), PHPStan should know this contains only ints
127+ $ result = $ pipeline
128+ ->filter (is_int (...))
129+ ->map (fn (int $ n ) => yield $ n * $ n )
130+ ->toList ();
131+
132+ $ this ->assertSame ([1 , 1764 ], $ result );
133+ }
134+
121135 /**
122136 * Tests that 'is_array' string callback narrows types correctly.
123137 */
@@ -138,6 +152,21 @@ public function testFilterWithIsArrayCallback(): void
138152 /**
139153 * Tests that multiple filters work together for type narrowing.
140154 */
155+ public function testChainedFilters (): void
156+ {
157+ /** @var Standard<int, int|string|null> $pipeline */
158+ $ pipeline = take ([1 , 'hello ' , null , 42 , 'world ' ]);
159+
160+ // Chain filters: first remove nulls, then keep only strings
161+ $ result = $ pipeline
162+ ->filter (strict: true ) // Removes null
163+ ->filter (is_string (...)) // Keeps only strings
164+ ->cast (fn (string $ s ) => strtoupper ($ s ))
165+ ->toList ();
166+
167+ $ this ->assertSame (['HELLO ' , 'WORLD ' ], $ result );
168+ }
169+
141170 /**
142171 * Tests that the extension works with complex union types.
143172 */
0 commit comments