Comment by bakugo

1 day ago

> This example exposes the "uninitialized" state that a property can be in, which is NOT the same as NULL. This distinction frustratingly comes up when you try to do a null check on these properties:

If you're accessing an uninitialized property or checking if a property is uninitialized, you're probably already doing something wrong.

The point of class properties with no default value is that you're supposed to set them either in the constructor, immediately after creating an instance, or via some other method that guarantees they'll have a value by the time you need to read them (such as deserialization with validation).

If you want your properties to have a default "unset" value that you can trivially check for, that's what null is for. The author doesn't make it clear whether they are aware that you can declare a nullable string and give it the default value of null, but I hope they are.

I think anyone would agree with the “you’re doing something wrong” part, but if you declare that a property is typed and non-nullable, it would be nice if a constructor that didn’t populate its non-nullable properties would cause an exception to be thrown or something, as the constructor didn’t construct a valid object by its own specification. The wrongdoing was in the constructor so the constructor should be where that happens, not the innocent caller later who trusts the type definition.

Maybe it’s too impossible to do that, but the behavior described seems like it puts you right back in the world of completely dynamic anything-goes (PHP’s legacy, basically).

I thought part of the point of types was to give the caller confidence that simply accessing a typed property is guaranteed to return a certain type (null being a type that may be included).

  • In theory, that can happen, yes, but in practice, it hasn't been a problem for me.

    Good third party libraries generally don't leave uninitialized properties laying around for you to trip on, and I find the ability to set non-nullable properties after the constructor to be quite convenient for things like Symfony entities.