<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kay W.</title>
    <description>The latest articles on DEV Community by Kay W. (@kaywgeek).</description>
    <link>https://dev.to/kaywgeek</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1824922%2F565035fb-f640-419d-89f7-ab09e0974897.jpeg</url>
      <title>DEV Community: Kay W.</title>
      <link>https://dev.to/kaywgeek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kaywgeek"/>
    <language>en</language>
    <item>
      <title>Stop guessing why PHPStan thinks your variable is null</title>
      <dc:creator>Kay W.</dc:creator>
      <pubDate>Mon, 25 May 2026 06:34:18 +0000</pubDate>
      <link>https://dev.to/kaywgeek/phpstan-expects-x-y-given-the-trace-it-doesnt-give-you-40le</link>
      <guid>https://dev.to/kaywgeek/phpstan-expects-x-y-given-the-trace-it-doesnt-give-you-40le</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pp89mmwzalle7u4dwhs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pp89mmwzalle7u4dwhs.gif" alt=" " width="600" height="390"&gt;&lt;/a&gt;&lt;br&gt;
You've seen this a thousand times:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parameter #1 $amount of method format() expects float, float|null given.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You know the &lt;em&gt;final&lt;/em&gt; type. You don't know &lt;strong&gt;how it got there&lt;/strong&gt; — which param, which assignment, which missing narrow let the &lt;code&gt;null&lt;/code&gt; slip in. So you scroll up, squint, guess, repeat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kayw-geek/phpstan-type-trace" rel="noopener noreferrer"&gt;&lt;code&gt;phpstan-type-trace&lt;/code&gt;&lt;/a&gt; prints the whole journey instead of just the destination:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$amount · App\PriceCalculator::format (up to L25)
  L16  param   float|null
  L20  narrow  Assert::notNull($amount)  =&amp;gt;  float    via AssertTypeSpecifyingExtension
  L25  read    float
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the bug is obvious. Param came in as &lt;code&gt;float|null&lt;/code&gt;, a narrow tightened it on L20. If your error fires before L20, you know exactly what's missing — no guessing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; kayw-geek/phpstan-type-trace
./vendor/bin/phpstan-trace inspect src/Foo.php:42 myVar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;via&lt;/code&gt; tag is the kicker: when a third-party extension (Larastan, webmozart/assert, your own) reshaped the type, it tells you &lt;strong&gt;which one to blame&lt;/strong&gt; — no more grepping the vendor tree.&lt;/p&gt;

&lt;h2&gt;
  
  
  It stops your AI from hallucinating types
&lt;/h2&gt;

&lt;p&gt;This is the part that matters for &lt;strong&gt;legacy codebases&lt;/strong&gt;. When an LLM agent chases PHPStan errors, it &lt;em&gt;guesses&lt;/em&gt; types from pattern-matching — and in a 10-year-old codebase, those guesses are confidently wrong.&lt;/p&gt;

&lt;p&gt;Ship it as a &lt;a href="https://github.com/kayw-geek/phpstan-type-trace" rel="noopener noreferrer"&gt;Claude Code skill&lt;/a&gt; and the agent calls the trace automatically. Fixes get grounded in &lt;strong&gt;real upstream type evidence&lt;/strong&gt;, not vibes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add kayw-geek/phpstan-type-trace
/plugin install phpstan-type-trace@kayw-geek
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A versioned &lt;code&gt;--json&lt;/code&gt; contract makes it safe for agents and CI to build on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now in your editor
&lt;/h2&gt;

&lt;p&gt;The same engine powers a &lt;a href="https://plugins.jetbrains.com/plugin/31962-phpstan-type-trace" rel="noopener noreferrer"&gt;PhpStorm plugin&lt;/a&gt;: caret on a variable → &lt;strong&gt;Trace Type at Caret&lt;/strong&gt; → the chain renders in a tool window with clickable lines, copyable types, and &lt;code&gt;via&lt;/code&gt; attribution pills. &lt;em&gt;(JetBrains' official account even liked the launch — hi 👋.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pp89mmwzalle7u4dwhs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0pp89mmwzalle7u4dwhs.gif" alt="PhpStorm with the phpstan-type-trace plugin: the caret sits on a variable, the Trace Type at Caret action runs, and a tool window opens listing the variable's full type-inference chain — param, narrow, and read events with line numbers, inferred types, and via-extension attribution pills." width="600" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kayw-geek.github.io/phpstan-type-trace/" rel="noopener noreferrer"&gt;Live examples&lt;/a&gt; — five real chains, 10 seconds, no install. If you've ever lost ten minutes hunting where a &lt;code&gt;null&lt;/code&gt; came from, this gives them back. Star the &lt;a href="https://github.com/kayw-geek/phpstan-type-trace" rel="noopener noreferrer"&gt;repo&lt;/a&gt; if it helps.&lt;/p&gt;

</description>
      <category>php</category>
      <category>phpstan</category>
    </item>
  </channel>
</rss>
