상현에 하루하루
개발자의 하루

PHP 8.1: Pure Intersection Types

( 업데이트: )

Pure Intersection Types 한글말로 순수 교차 유형? 순수교차타입은 설명하기에는 쉽지만 정적 분석기와 함께 사용하지 않은 경우 약간 모호하게 보일 수 있습니다. 당신은 이미 union type에 대해 알 것이다.

function test ( A | B $foo ) { /* ... */ }Code language: PHP (php)

이 것은 “$foo의 유현은 A또는 B 여야합니다”라고 말합니다.

function test ( A & B $foo ) { /* ... */ }Code language: PHP (php)

이 것은 A와 B여야 한다고 말합니다. 교차타입의 위처럼 보이고 아마 추측이 가능했을 것입니다.

그렇다면 이것은 언제 유용할까요?

예를 들어보겠습니다. 두 개의 인터페이스가 있다고 가정해 보겠습니다. 하나는 WithUuid, 다른 하나는 WithSlug입니다. 이름에서 그들이 하는 일을 꽤 명확하게 알 수 있다고 생각합니다. 하지만 우리가 같은 줄에 있는지 확인하기 위해 다음 두 인터페이스가 있습니다.

interface WithUuid {
  public function getUuid(): Uuid;
}
interface WithSlug {
  public function getSlug(): string;
}Code language: PHP (php)

이제 Uuid 와 Slug가 모두 있는 객체에서만 작동하는 함수가 있다고 상상해 보십시오. 아마도 그러한 객체에 대한 URL을 생성하는 함수

function url ($object): string { /* ... */ }Code language: PHP (php)

두 가지를 모두 구현하는 객체만 얻을 수 있도록 그러한 함수를 어떻게 타입 힌트를 적용하시겠습니까? 인터페이스 중 하나만 구현하는 개체도 허용하므로 union type 유형을 사용할 수 없습니다.

따라서 PHP 8.1 이전의 유일한 해결책은 WithUuidWithSlug를 모두 확장하는 새 인터페이스를 만드는 것이 었습니다.

interface WithUrl extends WithUuid, WithSlug {}Code language: PHP (php)

그래서 intersection types가 등장합니다. 교차 유현은 모든 곳에서 새 인터페이스를 만들 필요 없이 타입 사용에 더 많은 유연성을 추가합니다.

function url ( WithUuid & WithSlug $object) : string { /*...*/ }Code language: PHP (php)

꽤 깔끔한 방법입니다. 실제로 이것이 유용할 프로젝트의 몇 군데를 생각할 수 있습니다.

🚨 경고: Pure Intersection Types은 현재 null을 지원하지 않습니다.

url 함수가 올바른 인터페이스를 구현하거나 null을 구현하는 객체를 제외하기를 원했다면 지금은 Intersection Types를 사용할 수 없을 것입니다.

실제로 PHP 8.1에서 이 동작을 허용하기 위해서 논의가 계속 되고있지만 PHP 8.2로 연기될 가능성이 있습니다.