Constants were the last untyped declaration in the language, and 8.3 fixes that with the covariance rule you would expect.
interface Formatter
{
const string DEFAULT_LOCALE = 'en_GB';
}
class Uk implements Formatter
{
const string DEFAULT_LOCALE = 'en_GB'; // fine
}
class Broken implements Formatter
{
const int DEFAULT_LOCALE = 1; // Fatal
}
// and narrowing IS allowed, downwards only
class Base { const string|int VALUE = 'a'; }
class Child extends Base { const string VALUE = 'b'; }
The type is checked at compile time on the declaration and on every override, which catches the case this exists for: an interface constant documented as one type and implemented as another somewhere down the hierarchy. It is not a substitute for an enum — a fixed set of values still wants to be an enum — and its real audience is constants that are genuinely just typed values, which is most of them.