TGViewer
Пых Пых @phpyh · 7.83K subscribers
Post #509 5.69K
Пых 💙 Typhoon 0.4. self, parent, static. В Typhoon 0.3 я начал добавлять поддержку трейтов. И всё, естественно, поломалось. 🙈 Раунд 2 trait T { public function self(): self { return $this; } public function parent(): parent { return $this; } public…
💙 Typhoon 0.4. self, parent, static

Есть у меня одна черта: я периодически возвращаюсь ко всем своим костылям, пока не сделаю нормально или не уволюсь. О том, что для относительных типов не стоит использовать дженерики, кричали разные куски кода, но всегда казалось, что будет слишком жирно делать их first-class. А потом я задумался над тем, как работают с этими типами анонимные функции.

Раунд 3


final class A extends ArrayObject
{
public function self() { return fn (): self => new self(); }
public function parent() { return fn (): parent => new parent(); }
public function static() { return fn (): static => new static(); }
}

final class B extends stdClass {}

$self = (new A())->self();
echo $self()::class; // A
echo $self->call(new B)::class; // B

$parent = (new A())->parent();
echo $parent()::class; // ArrayObject
echo $parent->call(new B)::class; // stdClass

$static = (new A())->static();
echo $static()::class; // A
echo $static->call(new B)::class; // B


Получается, что self, parent и static отлично себя чувствуют в анонимных функциях и, как и в трейтах, резолвятся в зависимости от скоупа, в том числе поддерживают его изменение в рантайме. Посмотрев на этот сниппет, мы наконец-то согласились, что относительные типы класса везде в PHP ведут себя логично и единообразно и должны быть замоделированы как first-class типы.

Теперь в typhoon/type 0.4 можно создавать self, parent и static с классом скоупа и без него. Последнее как раз требуется в трейтах и непривязанных анонимных функциях. В TypeVisitor каждый относительный тип обрабатывается индивидуально. Ну и, конечно, поддерживаются аргументы типов (а-ля self<X, Y>). Комбо-пример:


trait T
{
/**
* @return array{self, parent, static}
*/
public function types(): array
{
return [$this, $this, $this];
}
}

abstract class A extends stdClass
{
use T;
}

final class B extends A {}

$type = TyphoonReflector::build()
->reflectClass(B::class)
->methods()['types']
->returnType();

echo stringify($type);

// array{self@A, parent@stdClass, static@B}
  • 👍 13
  • 🔥 3
  • 🤔 2
More from @phpyh
  1. Sep 30, 2026🍺 BeerPHP AI Moscow Кажется, «неделя PHP» потихоньку превращается в месяц PHP. 😅 Будет 2…
  2. Sep 28, 2026Запустили Пыхник и неделю PHP! Залетайте на первый открытый доклад от Дмитрия Dantes про к…
  3. Sep 15, 2026Сейчас один человек с AI может выполнять работу целого IT-отдела. Только хуёво
  4. Sep 12, 2026Спасибо за заявки! Всем напишу в понедельник. Осталось 1 место.
  5. Sep 11, 2026Хардкорный курс асинхронного PHP https://hardcourse.ru/php/async
  6. Sep 11, 2026Ещё полчасика надо — сайт готов, расписываю программу! 🙏
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →