본문 바로가기

IT

Effective Typescript - 11 - 잉여 속성 체크 한계 인지하기

타입이 명시된 변수에 객체 리터럴을 할당할 때 타입스크립트는 해당 타입의 속성이 있는지, 그리고 '그 외 속성이 없는지'를 확인합니다. (구조적 타이핑 무시)

 

interface Room {
    numDorrs: number,
    ceilingHeightFt: number;
}

const r: Room = {
    numDorrs : 1,
    ceilingHeightFt: 10,
    elephant: 'present' // 오류
};

const obj = {
    numDorrs : 1,
    ceilingHeightFt: 10,
    elephant: 'present'
};

const r: Room = obj // 정상, 임시 변수를 도입하면 잉여 속성 체크가 동작하지 않습니다.

위 예제에서 확인 되듯, 타입이 명시된 변수에 리터럴을 할당할 때는 구조적 타이핑이 무력화되는 것을 확인할 수 있습니다. 이와 같은 동작을 '잉여 속성 체크'라고 합니다.

여기서 임시 변수를 이용하여 할당하면, '잉여 속성 체크'가 동작하지 않는다는 점을 유의하시기 바랍니다.

 

타입스크립트는 단순히 런타임에 예외를 던지는 코드에 오류를 표시하는 것뿐 아니라, 의도와 다르게 작성된 코드까지 찾으려고 합니다.

declare function setDarkMode():void;

interface Options {
    title: string;
    darkMode?: boolean;
}

function createWindow(options: Options) {
    if(options.darkMode) {
        setDarkMode();
    }
}

createWindow({
    title: 'Spider Solitarie',
    darkmode: true // 오류
    //  Object literal may only specify known properties,
    //but 'darkmode' does not exist in type 'Options'. Did you mean to write 'darkMode'?(2345)
})

 

이와 같이 잉여 속성 체크를 이용하면 리터럴을 할당하는 과정에서 의도하지 않은 오타와 실수를 막는데 도움을 줍니다.

 

한편, 선택적 속성만 가지는 '약한(weak)' 타입에서도 비슷한 체크가 동작합니다.

interface LineChartOptions {
    logscale?: boolean;
    invertedYAxis?: boolean;
    areaChart?: boolean;
}

const opts = {
    logScale: true
};

const o: LineChartOptions = opts; // 오류 \n
//Type '{ logScale: boolean; }' has no properties in common with type 'LineChartOptions'.(2559)

이런 약한 타입에 대해서 타입스크립트는 값 타입과 선언 타입에 공통된 속성이 있는지 확인하는 별도의 체크를 수행합니다. '공통 속성 체크'는 잉여 속성 체크와 마찬가지로 오타를 잡는데 효과적이며 구조적으로 엄격하지 않습니다.

그러나 '잉여 속성 체크' 와 다르게, 약한 타입과 관련된 할당문마다 수행됩니다.

 

[요약]

* 객체 리터럴을 변수에 할당하거나 함수에 매개변수로 전달 할 때 잉여 속성 체크가 수행됩니다.

* 잉여 속성 체크는 오류를 찾는 효과적인 방법입니다. 구조적 타이핑 기능과 역할이 다릅니다.

* 할당의 개념을 정확히 알아야 잉여 속성 체크와 일반적인 구조적 할당 가능성 체크를 구분할 수 있습니다.

* 잉여 속성 체크에는 한계가 있습니다. 임시 변수를 도입하면 잉여 속성 체크를 건너 뛸 수 있다는 점을 기억해야 합니다.