Skip to content

Fix inherited PHPDoc / annotation type resolution#136

Open
ragulka wants to merge 2 commits intospatie:mainfrom
ragulka:fix/inherited-docblock-type-resolution
Open

Fix inherited PHPDoc / annotation type resolution#136
ragulka wants to merge 2 commits intospatie:mainfrom
ragulka:fix/inherited-docblock-type-resolution

Conversation

@ragulka
Copy link
Copy Markdown
Contributor

@ragulka ragulka commented Mar 26, 2026

Summary

When a child class inherits a property with a @var docblock annotation from a parent class in a different namespace, the type transpiler incorrectly resolves class references using the child class's namespace context. This causes types like SimpleGenericClass<int, string> to resolve as TypeScriptUnknown when the child doesn't import the referenced class.

Example

// Parent — namespace App\Models
class Parent {
    /** @var string[]|SimpleGenericClass<int, string> */
    public array $items;
}

// Child — namespace App\Models\Children (different namespace, no import)
class Child extends Parent {
    public string $ownProperty;
}

Transforming Child would produce unknown for the $items type instead of correctly resolving SimpleGenericClass.

Fix

In ClassTransformer::getTypeScriptNode(), when the annotation comes from the property's own @var docblock (rather than a class-level @property or constructor @param on the current class), use the declaring class's namespace context for type resolution.

This distinction matters because:

  • Class-level @property and constructor @param annotations are written in the current class's context and should resolve against its namespace
  • Property @var annotations belong to the declaring class and should resolve against that class's namespace

ragulka and others added 2 commits March 26, 2026 09:36
When a child class inherits a property with a PHPDoc @var annotation
that references a class (e.g. SomeGenericClass<int, string>), the
transpiler resolves the class name using the child class's file imports
and namespace — not the parent class's where the annotation is defined.

This causes the type to resolve as TypeScriptUnknown when the child
class is in a different namespace and doesn't import the referenced
class, even though the parent's namespace contains it.

The bug is in FindClassNameFqcnAction::execute() which uses
$node->getFileName() to load use statements, where $node is the class
being transformed (the child), not the class that declares the property
and its docblock.
When a child class inherits a property with a @var docblock from a parent
class, resolve type references using the declaring (parent) class's
namespace context instead of the child's. This fixes cases where the
child is in a different namespace and doesn't import the referenced class.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant