ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • (TypeScript) - 함수 타입의 호환성
    개발/TypeScript 2025. 8. 22. 16:04
    반응형

    ■ 함수 타입의 호환성

    : 특정 함수 타입을 다른 함수 타입으로 취급해도 괜찮은가를 판단하는 것이다.

     

    여기서는 두 가지를 확인하면 된다.

     

    1. 반환값의 타입이 호환되는가

    2. 매개변수의 타입이 호환되는가

     

    ■ 반환값이 호환되는가

    type A = () => number;
    type B = () => 10;
    
    let a: A = () => 10; // a 함수 반환값 number
    let b: B = () => 10; // b 함수 반환값 넘버 리터럴 타입
    
    a = b; // number <- 넘버 리터럴 (가능)
    b = a; // 넘버 리터럴 <- number (불가능)

     

    여기서 반환값만 비교해보자

    a 함수 반환값은 number, b 함수 반환값은 넘버 리터럴이다.

     

    밑을 보면 a = b 즉, number <- 넘버 리터럴은 가능하지만 (업캐스팅)

    b = a, 넘버리터럴 <- number 는 불가능하다. (다운캐스팅)

     

    ■ 매개변수가 호환되는가

    • 매개 변수의 개수 같을 때
    // 기준2. 매개변수가 호환되는가
    // 2-1. 매개변수의 개수가 같을 때
    
    type C = (value: number) => void;
    type D = (value: number) => void;
    
    let c: C = (value) => {};
    let d: D = (value) => {};
    
    c = d;
    d = c;

     

    다음과 같이 매개변수가 같고 반환값도 같다면 둘 다 호환이 된다.

     

    type C = (value: number) => void;
    type D = (value: 10) => void;
    
    let c: C = (value) => {};
    let d: D = (value) => {};
    
    c = d; //불가능
    d = c; //가능

     

    그러나 매개변수가 다를 경우, c=d 에서 오류가 난다.

     

    즉, c <- d 로 변환하는 number 리터럴 타입을 number 로 업캐스팅 하겠다는 건데

    반환값 타입을 기준으로 호환성 판단할 때와는 다르게 매개변수 타입을 기준으로 호환성을 평가할 때에는 오류가 난다.

     

    이와는 반대 케이스인 다운캐스팅이면 불가능해야하나 d <- c 는 또 가능하다.

     

    그러면 이러한 현상은 왜 일어날까?

     

    type Animal = {
        //슈퍼타입
        name: string;
    };
    
    type Dog = {
        //서브타입
        name: string;
        color: string;
    };
    
    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);
    };

     

    다음과 같이 Animal 타입과 Dog 타입을 만들어보자.

    그리고 나서 각각의 매개변수 타입을 지정하고 타입에 해당하는 프로퍼티를 출력하도록 설정한다.

     

    다음을 보면 animalFunc = dogFunc; 해주면 불가능하고,

    dogFunc = animalFunc; 하면 가능하다.

     

    이는 위에서 본 예시랑 동일하다.

    그 이유는 testFunc 를 찍어보면서 알 수 있다.

     

    animalFunc = dogFunc; 를 하게 해주면

    testFunc 에 있는 것처럼 매개변수의 타입은 Animal 로 가져가지만,

    해당 내용을 animalFunc 에 넣는 것이므로 본문 내용은 dogFunc 있는 내용을 다 가져간다.

     

    let testFunc = (animal: Animal) => { //불가능
        console.log(animal.name); //가능
        console.log(animal.color); //불가능
    };

     

    즉, 다음 코드처럼 만들어지는데 그러면 animal.name 은 불러와도 animal.color 는 불러오지 못하는 오류가 발생한다.

     

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

     

    반대로 dog 는 프로퍼티로 name 과 color 둘 다 가지고 있기 때문에

    animalFunc 의 본문인 console.log(animal.name); 만 찍어도 오류가 발생하지 않는 것이다.

     

    ■ 함수 타입의 호환성 정리

    함수 A 타입과 함수 B 타입이 있을 때 매개변수를 기준으로 호환성을 판단한다고 하면

    반환값 타입 호환성과는 다르게 업캐스팅으로 호환되는 것은 안되고, 다운캐스팅으로 호환되는 것이 가능하다.

     

    • 매개 변수의 개수가 다를 때
    // 2-2. 매개변수의 개수가 다를 때
    
    type Func1 = (a: number, b: number) => void;
    type Func2 = (a: number) => void;
    
    let func1: Func1 = (a, b) => {};
    let func2: Func2 = (a) => {};
    
    func1 = func2; //가능
    func2 = func1; //불가능

     

    매개 변수의 개수가 다를 때에는 func1 = func2; 는 가능하나 반대는 불가능하다.

    왜냐하면 func2 에 해당하는 Func2 의 매개변수 1개를 Func1 2개에 넣는 것은 가능하지만

    Func1 2개를 Func2 1개에 넣는 것은 불가능 하기 때문이다.

     

    type Func1 = (a: string, b: number) => void;
    type Func2 = (a: number) => void;
    
    let func1: Func1 = (a, b) => {};
    let func2: Func2 = (a) => {};
    
    func1 = func2;
    func2 = func1;

     

    단 다음과 같이 Func1 의 a 를 string 으로 바꿔서

    아예 매개변수 타입 자체가 다르면은 위 내용은 적용되지 않는다.

    반응형
Designed by Tistory.