강의

멘토링

로드맵

Inflearn brand logo image

인프런 커뮤니티 질문&답변

루룸님의 프로필 이미지
루룸

작성한 질문수

한 입 크기로 잘라먹는 타입스크립트(TypeScript)

유니온 타입 질문 드립니다

해결된 질문

작성

·

37

·

수정됨

0

유니온을 합집합 비유로 설명해주셨는데 이해가 잘 안 가서요

우선 지피티한테도 질문했는데, 제가 이해한대로 답변을 해주더라구요

[질문]

type Dog = {
  name: string;
  color: string;
};

type Person = {
  name: string;
  language: string;
}

type Union1 = Dog | Person ; 

let union1: Union1 = {
  name: "",
  color: "",
  language: "",
}

이런 경우에 union1는 불가능한 객체지? 왜냐하면 Union1 은 Dog 또는 Person 객체의 타입형태이어야 하는데, 

{
  name: "",
  color: "",
  language: "",
}

이런 형태는 그 어디에도 없으니까 

[GPT 답변]

맞습니다. Union1 타입은 Dog 타입 또는 Person 타입 중 하나를 가지도록 정의되어 있습니다. 그러나 아래와 같은 객체는 유효하지 않습니다:

let union1: Union1 = {
  name: "",
  color: "",
  language: "",
}

이 객체는 Dog 타입과 Person 타입을 동시에 포함하려고 시도하는 형태입니다. Union1Dog 또는 Person 타입 중 하나만 가져야 하므로, 둘 다 포함하는 객체는 유효하지 않습니다.

 

라고 하고 gemini나 클로드 다 같은 답을 하네요 ㅜ

 

Dog | Person -> Dog 타입 또는 Person 타입 둘 중 하나에 해당하는 타입일텐데

Dog도 Person도 아닌 객체인 name, color, language 이게 왜 가능한지 이해가 가지 않습니다..

 

union1 객체가 가능하면 아래 코드도 정상 동작해야 하지 않나요? 이건 또 오류가 나더라구요

type Person = {
  name: string;
  age: number;
}
type Developer = {
  name: string;
  skill: string;
}

function introduce(someone: Person | Developer) {
	console.log(someone.name);  // O 정상 동작
	console.log(someone.age);  // X 타입 오류
	console.log(someone.skill);  // X 타입 오류
}

(인프런 AI 인턴도 union1 객체가 불가능 하다고 답변주네요 ㅜ)

답변 2

2

이정환 Winterlood님의 프로필 이미지
이정환 Winterlood
지식공유자

안녕하세요 이정환입니다.

우선 강의에서 말씀드렸듯이 아래의 코드에서 union1 변수는 타입 오류가 발생하지 않습니다. 즉 Union1 타입에는 union1 변수의 값이 포함됩니다.

type Dog = {
  name: string;
  color: string;
};

type Person = {
  name: string;
  language: string;
}

type Union1 = Dog | Person ; 

let union1: Union1 = {
  name: "",
  color: "",
  language: "",
}

 

강의에서 말씀드리고 있듯

타입스크립트에서 객체의 유니온(합집합) 타입은 프로퍼티 기준이 아닌, 값을 기준으로 생성됩니다.

따라서 Dog | Person 유니온 타입은, Dog 타입과 Person 타입의 합집합 타입으로

Dog 타입의 포함되는 값이거나, Person 타입에 포함되는 값의 집합을 의미합니다.

 

type Dog = {
  name: string;
  color: string;
};

type Person = {
  name: string;
  language: string;
}

type Union1 = Dog | Person ; 

그렇다면 어떤 값이 Dog 타입에 해당되려면 어떤 조건을 갖춰야 하죠? 정답은 name, color 프로퍼티를 갖는 객체여야 합니다. 두 프로퍼티를 갖추었다면 추가적인 프로퍼티를 가지고 있더라도 문제가 되지 않습니다. (객체 타입 참고)

이어서 이번에는, 어떤 값이 Person 타입에 해당하려면 어떤 조건을 갖춰야 하죠? 정답은 name, language 프로퍼티를 갖는 객체여야 합니다. 두 프로퍼티를 갖추었다면 추가적인 프로퍼티를 가지고 있더라도 문제가 되지 않습니다. (객체 타입 참고)

그럼 아래의 union1 변수에 저장된 객체 값은 어떤 타입에 포함될 수 있을까요?

let union1: Union1 = {
  name: "",
  color: "",
  language: "",
}

정답은 name, color 프로퍼티를 가지고 있으니 Dog 타입에 포함될 수 있고, 동시에 name, language 프로퍼티를 가지고 있으니 Person 타입에도 포함될 수 있습니다. 즉 이 값은 두 타입의 교집합에 해당하는 값 입니다.

 

이때, 그렇다면 아래의 코드는 오류가 발생하지 않아야 맞는게 아니냐고 질문 주셨는데요

type Person = {
  name: string;
  age: number;
}
type Developer = {
  name: string;
  skill: string;
}

function introduce(someone: Person | Developer) {
	console.log(someone.name);  // O 정상 동작
	console.log(someone.age);  // X 타입 오류
	console.log(someone.skill);  // X 타입 오류
}

someone.age와 someone.skill에 접근했을때 오류가 발생하는 이유는 생각해보면 단순합니다. Person과 Developer의 합집합에 해당하는 값에는 모두 age나 skill 프로퍼티가 있는게 아니기 때문입니다.

name, skill 프로퍼티만 가지고 있는 객체도 Person | Developer 타입에 포함될 수 있고, 반대로 name, age 프로퍼티만 가지고 있는 객체도 Person | Developer 타입에 포함될 수 있습니다.

따라서 Person | Developer 타입에 포함되는 모든 객체 값들은 name 프로퍼티는 확실히 갖겠지만, age나 skill 프로퍼티는 있을수도 있고 없을 수도 있는 상황입니다.

그러므로 위 코드에서 someone.age 또는 someone.skill 처럼 이 프로퍼티가 분명히 존재할거라 가정하고 접근하게 되면 오류가 발생하게 됩니다. 있을지도 모른다와 있다는 다르니까요.

루룸님의 프로필 이미지
루룸
질문자

 

type Dog = { name: string; color: string };
type Person = { name: string; language: string };

type Union1 = Dog | Person;
type InterSection = Dog & Person;

const union1: Union1 = {
  name: "A",
  color: "blue",
  language: "en",
};

const interSection1: InterSection = {
  name: "B",
  color: "red",
  language: "ko",
};

그러면 위 코드처럼 union1 객체가 interSection1 객체와 동일하게 할당 가능하니

아래 코드 호출이 가능해야 하지 않나요? 에러가 떠서요

console.log(union1.color);
image.png

 

이정환 Winterlood님의 프로필 이미지
이정환 Winterlood
지식공유자

안녕하세요 이정환입니다.

union1.color와 union1.language에 오류가 발생하는 이유는 위 답변에 달아드린 이유와 동일합니다. 아래 그림으로 첨부해 드린 부분을 자세히 살펴봐주세요

image.png

 

이해가 어려우실 수 있으니 추가로 보내주신 아래의 예제에서 다시 설명해드리자면

type Dog = { name: string; color: string };
type Person = { name: string; language: string };

type Union1 = Dog | Person;
type InterSection = Dog & Person;

const union1: Union1 = {
  name: "A",
  color: "blue",
  language: "en",
};

union1.name // 정상
union1.color // 오류
union1.language // 오류

union1.name에 접근하는건 괜찮지만, union1.color와 union1.language에 접근하면 오류가 발생하는 이유는, 타입스크립트는 현재 union1 변수에 아래의 값들이 포함될 수 있다고 가정하기 때문입니다.

  • Dog 타입에 속하는 값 : name, color 프로퍼티가 있음

  • Person 타입에 속하는 값 : name, language 프로퍼티가 있음

  • Dog와 Person에 공통으로 속하는 값 : name, color, language 프로퍼티가 있음

따라서 name, color, language 프로퍼티 중 확실히 존재할거라고 보장할 수 있는 프로퍼티는 name 밖에 없습니다. color가 있을 경우 language가 없을 수 있고, 반대로 language가 있을 경우 color가 없을 수 있으니까요

이런 이유에서 확실히 있다고 보장할 수 있는 name 프로퍼티에만 접근을 허용하고 그렇지 않은 두 프로퍼티에는 접근을 불허 하는 것 입니다.

0

안녕하세요, 인프런 AI 인턴입니다. 루룸님.

질문해 주신 유니온 타입에 대해 혼란이 있으신 것 같네요. Union 타입은 말 그대로 하나 이상의 타입을 가질 수 있는 타입을 뜻합니다. 이 경우, Dog 타입이나 Person 타입 중 하나로서만 객체를 구성해야 합니다.

유니온 타입 (Union Type)에 대한 설명

Dog | PersonDog 타입이나 Person 타입 중 어느 하나의 형태를 완벽히 갖추면 될 수 있도록 정의된 타입입니다. 그렇기 때문에, name, color, language 모두 포함한 객체는 유니온 타입에 맞지 않으며, 다음과 같은 경우에만 유효합니다:

  • Dog 타입인 { name: "", color: "" }
  • Person 타입인 { name: "", language: "" }

현재 주어진 코드:

let union1: Union1 = {
  name: "",
  color: "",
  language: "",
}

위와 같은 객체는 Union1 타입에 호환되지 않습니다. 올바르게 사용하려면 전부 포함하지 않고, Dog또는 Person 중 하나만 완전히 갖춘 형태여야 합니다. 이는 타입 단위에서 유니온 | 연산자는 두 타입 중 하나여야 한다는 제약을 가집니다.

추가 설명

  • 유니온 타입은 포함 관계를 허용하지 않습니다. 각 타입의 모든 필드를 가질 필요는 없고, 그 중 하나라도 완전한 구성이면 가능합니다.
  • 혼합된 형태, 즉 서로 다른 타입 필드가 결합된 형태는 타입스크립트 유니온 정의에 부합하지 않습니다.

관련된 질문과 답변을 통해 더 이해를 돕고자 합니다:
- 교집합 타입 질문있습니다

저는 질문자님의 이해를 돕고자 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

루룸님의 프로필 이미지
루룸

작성한 질문수

질문하기