====== PHP RFC: Type Aliases ====== * Version: 1.1 * Date: 2025-12-02 * Author: Robert Landers, landers.robert@gmail.com * Status: Under Discussion * Implementation: https://github.com/php/php-src/pull/20635 ===== Introduction ===== Type aliases provide a mechanism to create more descriptive and readable type hints in PHP code. This RFC proposes type aliases that are resolved at compile time, improving code readability and maintainability while keeping the implementation simple and performant. Type aliases follow the same scoping rules as other ''%%use%%'' imports (classes, functions, constants). ===== Proposal ===== This RFC proposes type aliases that are resolved entirely at compile time. Unlike approaches that create runtime type representations, these aliases are simple compile-time substitutions - the alias is replaced with its underlying type during compilation and has no runtime existence. Type aliases follow the same scoping rules as other ''%%use%%'' imports to maintain consistency with existing PHP behavior. ==== Syntax ==== === Defining Type Aliases === Type aliases are defined using the extended ''%%use%%'' statement with the ''%%type%%'' keyword: The syntax is: ''%%use type as ;%%'' Supported type expressions: * Primitives: ''%%int%%'', ''%%string%%'', ''%%float%%'', ''%%bool%%'', ''%%array%%'', ''%%object%%'', ''%%mixed%%'', ''%%null%%'', ''%%true%%'', ''%%false%%'' * Classes and interfaces: ''%%\App\User%%'', ''%%Countable%%'' * Nullable types: ''%%?string%%'', ''%%?int%%'' * Union types: ''%%int|float%%'', ''%%string|Stringable%%'' * Intersection types: ''%%Countable&Traversable%%'' * DNF types: ''%%User|(Admin&Authenticated)%%'' Excluded type expressions: * ''%%void%%'' - cannot match any value * ''%%never%%'' - cannot match any value === Importing Type Aliases === Type aliases can be shared across files using ''%%include types%%'': The ''%%include types%%'' statement imports type aliases into the current scope, following the same scoping rules as ''%%use type%%'': **Important**: Types files must only contain type alias declarations. Any other code (functions, classes, statements) will result in a compile error: ==== Behavior ==== === Compile-Time Resolution === Type aliases are resolved at compile time through simple substitution. When the compiler encounters an alias in a type position, it replaces it with the underlying type expression: === Nested Aliases === Aliases can reference other aliases defined earlier in the same scope: === Scope Rules === Type aliases follow the same scoping rules as other ''%%use%%'' import statements (classes, functions, constants). This ensures consistent and predictable behavior: **No namespace** - type aliases apply to the whole file: **Curly brace scoped namespace** - type aliases apply only within the namespace block: **Single unscoped namespace** - type aliases apply to the whole file: **Multiple unscoped namespaces** - type aliases apply until the next namespace declaration: === Shadowing === Type aliases follow the same shadowing rules as class imports. An alias shadows any class with the same name in the current scope: === Namespace Resolution === Class names in type expressions are resolved according to standard PHP namespace rules at the point of alias definition: For ''%%include types%%'', types files must not contain namespace declarations. Any class references in types files must use fully qualified names: ==== Examples ==== Basic type alias usage: Type error shows expanded type: Shared types across files: ===== Backward Incompatible Changes ===== ==== New Keywords ==== This RFC introduces ''%%type%%'' and ''%%types%%'' as context-sensitive keywords. They can still be used as class, function, and method names, but have special meaning in the following contexts: * ''%%use type ...%%'' - defines a type alias * ''%%include types ...%%'' - imports type aliases from a file Impact assessment using grep.app and GitHub search shows minimal usage of ''%%type%%'' and ''%%types%%'' as identifiers in positions that would conflict. ===== Proposed PHP Version(s) ===== Next PHP 8.x (PHP 8.5 or later) ===== RFC Impact ===== ==== To the Ecosystem ==== **IDEs and Language Servers**: Will need updates to understand the new syntax and provide: * Autocomplete for type aliases * Go-to-definition for aliases * Expansion of aliases in hover information **Static Analyzers** (PHPStan, Psalm): Will need to parse the new syntax and resolve aliases during analysis. The compile-time nature makes this straightforward. **Documentation Tools**: May want to document type aliases or show expanded types. ==== To Existing Extensions ==== No impact. Type aliases are resolved at compile time and do not affect runtime behavior or extension APIs. ==== To SAPIs ==== No impact. ===== Open Issues ===== None currently. ===== Future Scope ===== The following features are explicitly not part of this RFC but could be considered in future proposals: * **Global/exportable type aliases**: Type aliases that can be autoloaded and used across the project without explicit imports * **Reflection support**: Runtime reflection of type aliases via ReflectionTypeAlias or similar * **Callable signatures**: ''%%use type callable(int): string as IntToString;%%'' * **Array shapes**: ''%%use type array{x: int, y: int} as Point;%%'' * **Generic type aliases**: ''%%use type array as Map;%%'' ===== Voting Choices ===== Primary vote requiring a 2/3 majority: * Yes * No * Abstain ===== Patches and Tests ===== Proof of concept implementation: https://github.com/php/php-src/pull/20635 The implementation includes: * Lexer and parser changes for ''%%use type%%'' and ''%%include types%%'' syntax * Compiler changes for type alias storage and resolution * Test coverage for basic usage, nested aliases, error cases ===== Implementation ===== After the RFC is implemented, this section should contain: - the version(s) it was merged into - a link to the git commit(s) - a link to the PHP manual entry for the feature ===== References ===== * Previous type alias discussions on php-internals * [[https://externals.io/message/121466|Basic Type Alias discussion]] * [[https://externals.io/message/125455|Typed Aliases RFC discussion]] * [[https://wiki.php.net/rfc/pattern-matching|Pattern Matching RFC]] (related type system work) ===== Rejected Features ===== * **Runtime type aliases (type_alias() function)**: Rejected in favor of compile-time-only approach for simplicity and performance * **Global exportable aliases**: Deferred to future scope due to autoloading complexity * **Aliases as special classes**: Rejected in favor of simple compile-time substitution * **Namespace support in types files**: Rejected to keep types files simple and avoid namespace resolution complexity ===== Changelog ===== * 2025-12-02 v1.1: Clarified that type aliases follow standard PHP ''%%use%%'' scoping rules (namespace-scoped, not file-scoped). Added detailed examples for different namespace configurations. * 2025-12-02 v1.0: Initial draft with type aliases and include types syntax