dnf类型是php 8.2引入的书写规则,要求联合类型与交集类型混合使用时必须用括号显式分组交集部分,如(string & jsonserializable) | (int & countable),以消除解析歧义。

PHP 8.2 引入的 DNF 类型(Disjunctive Normal Form types),本质是让联合类型(union)和交集类型(intersection)能安全、明确地混合使用。它不是一种新类型,而是一种书写规则:当你同时用 |(并集)和 &(交集)时,必须用括号把交集部分显式分组,确保逻辑清晰、解析无歧义。
DNF 类型的核心写法规则
只允许两种结构:
-
纯并集:如
string|int|float -
并集中的每个分支可含括号包裹的交集:如
(string & JsonSerializable) | (int & Countable)
❌ 错误写法(无括号、优先级模糊):string & JsonSerializable | int & Countable
这会被解释为 (string & JsonSerializable | int) & Countable,不符合 DNF 要求,PHP 会报语法错误。
常见合法组合示例
以下写法全部有效,且语义明确:
-
(array & Traversable) | null→ “要么是既为数组又可遍历的对象,要么是 null” -
(string & Stringable) | (int & BackedEnum)→ “字符串且实现了 Stringable,或整数且是枚举底层值” -
true | false | null→ 这是合法的纯并集(注意:PHP 8.2 起true、false、null可独立使用) -
(callable & array) | Closure→ “要么是数组形式的 callable(如['Class', 'method']),要么是 Closure 对象”
为什么必须加括号?
因为 PHP 不定义 & 和 | 的默认结合顺序。不加括号会导致类型系统无法确定你是想表达:
- A 或 B,且 C?→
(A | B) & C - A,或 B 且 C?→
A | (B & C)
DNF 强制你选一种,并用括号写清楚。这避免了类型推导歧义,也便于 IDE 和静态分析工具准确理解意图。
搭配只读类或字面量类型更实用
DNF 类型常和 PHP 8.2 其他特性协同使用:
- 与
readonly class结合:声明一个方法返回“只读用户对象或 null” →readonly User | null - 与字面量类型组合:
42 | 'hello' | true是合法类型,表示仅接受这三个确切值 - 配合接口约束:
(JsonSerializable & ArrayAccess) | stdClass表示“支持序列化+数组访问的对象,或标准对象”
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











