-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
After some days of testing, our team consistently found that the generic type system seems to basic and not very useful.
To give a couple of quick examples of things we tried that, to our suprise, didn't work:
<?hh
class Repository<T> {
// ...
}
class User {
// ...
}
$user_repo = new Repository<User>(); // nope :-(
And:
<?hh
class Hook<T> {
// ...
}
function hook<T>() : Hook<T> {
return new Hook<T>(); // nope :-(
}
$some_hook = hook<LoginEvent>(); // nope :-(
It seems that generics work only in declarations (extends, implements, etc.) but never in expressions? That's not very useful and prevents many common and useful patterns with generics.
It appears to be this way because generics are only type-hints and don't really seem to have a run-time footprint? To explain this better, here's an example of something class-related in PHP:
<?php
class Foo {
public static function hello() {
var_dump(get_called_class());
}
}
class Bar extends Foo {
}
Foo::hello(); // => "Foo"
Bar::hello(); // => "Bar"
Point being, type-names generated at call-time actually "exist" and can be obtained at run-time. The same is true for most type-related things in PHP - reflection will let you discover lots of type-related information at run-time.
In contrast, generic type arguments in Hack don't seem to "exist" at run-time - they are static type-hints only? This doesn't seem true to PHP as such - for example, it would seem natural to expect something like the following to work:
class Foo<T> {}
class Bar {}
$foo = new Foo<Bar>();
$class = new ReflectionClass($foo);
echo $class->getTypeArgument(0)->getClass()->getName(); // => "Bar"
We encountered other surprising behaviors, but I'm not going to get into them all - bottom, there were too many surprises and shortcomings for developers who are familiar with generics in other languages like C# and TypeScript.