inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

유니온 타입 질문 드립니다

해결된 질문

106

루룸

작성한 질문수 16

1

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

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

[질문]

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 객체가 불가능 하다고 답변주네요 ㅜ)

typescript

답변 2

2

이정환 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 처럼 이 프로퍼티가 분명히 존재할거라 가정하고 접근하게 되면 오류가 발생하게 됩니다. 있을지도 모른다와 있다는 다르니까요.

0

루룸

 

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

 

0

이정환 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 인턴

안녕하세요, 인프런 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 중 하나만 완전히 갖춘 형태여야 합니다. 이는 타입 단위에서 유니온 | 연산자는 두 타입 중 하나여야 한다는 제약을 가집니다.

추가 설명

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

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

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

핸드북 light/dark mode 관련 이슈가 있는 것 같습니다.

0

35

1

제네릭 클래스 핸드북 페이지가 undefined라고 나옵니다.

0

33

2

적절한 타입 찾기 React.ChangeEvent<HTMLInputElemen>

0

41

2

outDir 옵션 추가 후 컴파일 오류 질문

0

96

1

호출 시그니처 질문

0

75

2

서로소 유니언 타입이 discriminated union과 동의어 인가요?

0

88

2

조건부타입소개 중 함수오버로딩 활용 시 인수의타입과 함수의 반환값의 타입이 깨지는 문제

0

77

1

할인쿠폰 관련하여

0

174

2

프론트엔드에서의 인터페이스활용

0

107

2

안녕하세요 이정환님!

0

99

1

Node.js 설치에 관한 질문입니다.

0

87

2

함수 타입 호출 시그니처

0

65

1

35강. 모듈 보강은 라이브러리 파일을 직접 편집해야 하나요?

0

72

2

인터페이스 문법이 있는데 타입 별칭 문법은 왜 있나요?

0

125

4

마우스 호버 시 정보

0

103

2

vite으로 리액트 빌드하기를 업데이트해주세요.

1

93

2

타입가드를 만들어 사용하는 이유가 궁금합니다.

0

93

2

섹션 12가 너무 어려운데... 정상이겠죠..?

0

143

2

선생님.. 알고리즘도 강의해주시면안되나요

0

107

2

선생님은 어떻게 이런걸 아세요?

0

138

1

type: module

0

108

2

7:17초 업캐스팅 질문이있습니다!

0

86

1

슈퍼타입질문

1

75

2

프로젝트 설치

0

119

2