인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

한상윤님의 프로필 이미지
한상윤

작성한 질문수

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

함수 타입의 호환성

함수 타입의 호환성에 대해서 궁금한 사항이 있습니다.

해결된 질문

작성

·

311

·

수정됨

0

선생님 안녕하세요:) 이직을 위해서 선생님 강의로 타입스크립트 열심히 달리는 학생1입니다! 궁금한 사항을 30분정도 고민해봤는데 잘 모르겠어서 질문 남깁니다...

 

궁금한 사항 1 (수업 이외에 궁금한 사항입니다.)

Animal타입은 Dog타입의 슈퍼타입이기 떄문에, testFunc라는 함수에 매개변수로 dog를 대신 넣어 줄 수 있습니다.

type Animal = {
    name: string;
    color?: string;
};

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

let animal: Animal = {
    name: "동물",
}

let dog: Dog = {
    name: "멍멍이",
    color: "브라운",
}

let testFunc = (animal: Animal) => {
    console.log(animal.name)
    console.log(animal.color)

    // 혹은

    console.log(dog.name)
    console.log(dog.color)
}

testFunc(dog);

 

testFunc 매개변수를 animal: Animal로 받았기 때문에, animal로 출력하는게 맞는지 dog로 출력하는게 맞는지 알 수 있을까요? 만약 animal 변수 프로퍼티에 color가 없다면 dog로 받아야 되는게 맞지 않을까요?

let testFunc = (animal: Animal) => {
    console.log(animal.name)
    console.log(animal.color)

    // 혹은

    console.log(dog.name)
    console.log(dog.color)
}

 

추가 궁금한 사항 > 실무에서 이런 식으로 타입이 다른 매개변수를 받는 일이 많을까요?? 공부하면서 문득 드는 생각이였습니다. ㅜㅜ

 

궁금한 사항2 (수업과 관련된 이야기)

함수내 매개변수 호환성을 따젔을떄 다운 캐스팅이 코드상 더 안전하기 떄문에 업 캐스팅은 안되고 다운캐스팅은 가능하다고 하셨습니다. 이 내용이 질문 1과 관련이 있는 이야기일까요?

let animalFunc = (animal: Animal) => {
  console.log(animal.name);
};

let dogFunc = (dog: Dog) => {
  console.log(dog.name);
  console.log(dog.color);
};

animalFunc = dogFunc;
dogFunc = animalFunc;

let testFunc = (animal: Animal) => {
  console.log(animal.name)
  console.log(animal.color)
}

let testFunc2 = (dog: Dog) => {
  console.log(dog.name);
}

답변 1

1

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

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

순서대로 답변 드리겠습니다.

1번 질문

우선 타입을 다음과 같이 정의하셨는데요

type Animal = {
    name: string;
    color?: string;
};

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

보통 이렇게 Animal 같은 추상적인 존재를 슈퍼 타입으로 정의할 때에는 서브 타입들이 모두 공통으로 갖는 프로퍼티만 보유하도록 정의합니다. 따라서 위 Animal 타입의 color 프로퍼티는 굳이 정의되지 않는 편이 더 좋아보입니다.

따라서 아래와 같이 정의해보겠습니다.

type Animal = {
    name: string;
};

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

다음으로는 이렇게 두 타입을 정의한 상황에서 질문자님께서 작성해주신 testfunc에 대해 살펴보겠습니다.

let testFunc = (animal: Animal) => {
    console.log(animal.name)
    console.log(animal.color)

    // 혹은

    console.log(dog.name)
    console.log(dog.color)
}

testFunc(dog);

testFunc 함수는 Animal 타입의 매개변수를 제공받도록 되어 있습니다. 그럼 이 함수 내부에서는 Animal 타입의 값 그리고 Animal 타입의 모든 서브타입의 값을 제공받을 수 있게 됩니다. 그리고 이렇게 제공받은 모든 값들은 Animal 타입의 값으로 취급됩니다.
이렇게 되면 이제 testFunc 함수 내부에서는 모든 동물들이 수행할 수 있는 기능만 작성하는게 좋습니다.
따라서 color 처럼 Dog 타입의 값들만이 갖는 값들은 여기서는 사용하지 않아야 합니다.

실무에서 이렇게 사용하는 경우는 꽤 많습니다. 단 이렇게 슈퍼 타입의 매개변수를 받는 함수 내부에서는 모든 서브타입의 값들이 동일하게 동작할 수 있는 기능만 사용한다는 점을 꼭 기억해주시기 바랍니다.

또 추가로 앞서 말씀해드린 것 처럼 슈퍼타입과 서브타입을 나눌 때에는 슈퍼타입은 반드시 모든 서브타입에 공통으로 존재하는 프로퍼티만 정의되어 있어야 한다는 점도 함께 기억해주시면 좋겠습니다.

2번 질문

엇 이 부분은 뭔가 오해가 있으신 것 같은데요

강의에서는 아래 그림 자료처럼 업캐스팅이 안전하고 다운 캐스팅은 안전하지 않다고 설명합니다.

image3섹션-타입은 집합이다의 6분 경을 참고하시면 됩니다.

 

한상윤님의 프로필 이미지
한상윤
질문자

헉! 궁금한 사항 너무 정확하게 설명해주셔서 궁금증이 해결되었습니다! 특히 2번 질문이 가장 궁금했는데 공통으로 선언된 프로퍼티만 쓰는게 맞군요!! 감사합니다 선생님:)

한상윤님의 프로필 이미지
한상윤

작성한 질문수

질문하기