Wendell Adriel, a senior software engineer on the Laravel OSS team, has published a draft RFC titled “Typed array declarations” on the PHP internals mailing list. The proposal is available at https://wiki.php.net/rfc/typed_array_declarations and was discussed in a thread starting on 16 July 2026.

The RFC would let developers declare the types of array values and, optionally, keys. The syntax `array<TValue>` would mean an array with integer keys, while `array<TKey, TValue>` would be used when the key type must be explicit. Existing plain `array` declarations would remain unchanged.

The draft defines three implementation levels that share the same syntax and Reflection metadata but differ in enforcement. Level 1 parses the declaration and exposes it via Reflection, but never checks individual elements. Level 2 validates keys and values when an array crosses a declared boundary, such as a complete property assignment, function argument, return value, default value, or typed class constant; however, direct dimension writes like `$obj->prop['x'] = ...` are still accepted. Level 3 includes Level 2 and also enforces the type on later property mutations and references, so both whole-property assignment and direct dimension writes would throw a `TypeError` before the invalid value is stored. Adriel currently recommends Level 3 for typed properties because it preserves the guarantee the declaration appears to make. No implementation exists yet; he asked for feedback on runtime semantics and the appropriate level before coding.

Lazare Inepologlou responded first. He noted that since the RFC limits keys to `int` or `string`, neither can be subtyped, so a key subtype relation `K1 <: K2` can never apply and only `K1 = K2` is possible. He also argued that value covariance is only sound for read-only arrays; write operations place the value type in a contravariant position, so sound covariant subtyping would require clearly separating read and write interfaces. Adriel published a v0.2 of the RFC incorporating this feedback.

Rob Landers then raised broader concerns. He said the proposal overlaps significantly with the reified generics RFC, which is currently on hold until after the current code freeze, with discussion not expected to resume until late August or early September at the earliest. Both proposals must address the same questions around parameterized types, variance, Reflection, runtime enforcement, inference, and type identity, so he warned against committing PHP to array-specific rules before the broader generics design has been discussed. Otherwise, the language could either constrain generics or end up with two incompatible parameterization models.

Landers also criticized the proposed variance model. For a mutable built-in collection, variance is normally unsafe unless the API clearly separates reads from writes. The reified generics RFC therefore makes generic parameters invariant by default and allows covariance or contravariance only where proven safe. The typed-array draft, by contrast, treats `array<Dog>` as compatible with `array<Animal>` only at selected by-value boundaries, relying on PHP’s copy-on-write separation, then becomes invariant for writable aliases and adds extra rules for shared references. Landers argued this is not a normal subtype relationship but context-dependent boundary compatibility that depends on engine-level array separation and reference behavior, which would be hard for users to understand and hard for the engine to enforce consistently. He suggested making parameterized arrays invariant, for example `array<int, Dog>` is not a subtype of `array<int, Animal>`, and offering covariance through a separate read-only collection or interface if desired.

Landers also found the one-argument syntax `array<TValue>` confusing because it implicitly means `array<int, TValue>`. It is not a general array-of-values because string keys are rejected, yet it is not a true list because the integer keys need not be contiguous or start at zero. He would expect `array<TValue>` to constrain only the value type while leaving the key type as `int|string`, and suggested a future `list<TValue>` for the stricter numeric-keyed form.

A final concern was repeated runtime validation. Because ordinary PHP arrays do not store a trusted element-type identity, passing an array through an untyped boundary loses any earlier type guarantee. At every subsequent typed boundary, PHP must recursively validate the whole array again. For large or nested arrays, this can introduce O(n) or recursive O(n) cost at every call. Landers therefore strongly preferred waiting for the generics RFC or, at minimum, limiting the typed-array RFC to syntax and Reflection experimentation without committing to independent variance and runtime semantics.

Adriel replied that he agreed with the concerns. He said two paths are now possible: do only Level 1 for this RFC, which is simple enough for PHP 8.7, and defer Level 2 and Level 3 to a later RFC after the generics design is settled; or defer the whole RFC until after generics and then aim for Level 2 or Level 3, with Level 3 as his preferred outcome. He said he had now published a v0.2 and would be happy with either approach.