Without type annotations: function foo($b) {
if (!is_string($b)) { // Ugh, why can't the language enforce this? throw new Exception("needed a string"); } } With type annotations: function foo(string $b) { // I know $b is a string. I don't need to check. :) } Without unions: function foo($b) { if (is_string($b)) { // ... } else if ($b instanceof Bar) { // ... } else { // Ugh, why can't the language enforce this? throw new Exception("needed a string|Bar"); } } With unions: function foo(Bar|string $b) { if (is_string($b)) { // ... } else { // I know $b is a Bar here. I don't need to check. :) } } In both cases, the type annotation has removed the 1 check and the need to throw an exception. It's the exact same benefit. On Sat, Apr 16, 2016 at 1:10 AM, Andrea Faulds <a...@ajf.me> wrote: > Hi Stas, > > Stanislav Malyshev wrote: > >> I don't know what is complicated about "string|Stringable" or "Foo|Bar" >>> since it is super self-explanatory. However, I find myself checking the >>> >> >> It may be self-explanatory for you. It's much less self-explanatory for >> somebody just starting to learn. It is also very dangerous - if it's >> either Foo or Bar, can you call Foo::stuff on it or not? If it's string >> or not string, can you call strlen on it? Etc., etc. It adds a lot of >> cognitive load and complicates the whole picture. You may have a >> specific use case where it is useful (which we have yet to see btw) but >> please remember it's a language with literally millions of use cases and >> users. >> > > This is something that particularly concerns me about union types, in that > they reduce type safety. If you have a union type of Foo|Bar for some > variable, then the set of methods you can call on that variable is actually > the intersection, not the union, of the set of methods you can call on Foo > and Bar. Which, unless those two classes share some interface, is probably > an empty set. So there's nothing you can actually do safely with it without > doing checks within the body of the function, and if you're doing that, > then why do we have a type declaration? It's only barely more useful than > omitting a type declaration at all; type declarations are supposed to > prevent you needing to check. On the other hand, if the two classes share > some methods, then either there's an interface you can already use here, or > you can create one. Either way, you don't need a union type. > > There are some cases where you can't create an interface, but if that's > the case, I think it is more worthwhile to look at how we can fix those > cases, rather than add what amounts to a hacky workaround. > > Thanks! > -- > Andrea Faulds > https://ajf.me/ > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >