[TS] any 타입의 함정

Jeerryy·2024년 7월 19일
0

Typescript

목록 보기
1/1
class NumberClass {
    private readonly id: number;
    constructor(id: number){
        this.id = id;
    }

    toString():string{
        return `${typeof this.id}`
    }
}



export function main(){

    const stringNumber:any = "124214";

    
    const numClass = new NumberClass(stringNumber);

    console.log(numClass.toString());
}

main();

위 코드를 실행 했을 때 어떤 값이 출력될 것 같나요?

string? number?

정답은 string 입니다.

왜일까요? 바로 제목 그대로 any 타입의 함정입니다.

any 타입의 특징은 아래와 같습니다

  • 해당 값에 대해서 임의의 속성 접근 가능

  • 함수처럼 호출 가능

  • 다른 임의 타입의 값 할당 가능

  • 타입 검사 하지 않음

4 번째의 특징에 따라 컴파일 에러에 잡히지 않습니다.

any 타입인 string 값을 파라미터로 사용했지만 컴파일 에러가 발생하지 않는다.

컴파일 후 js 코드로 본다면 이유에 대해 더 명확하게 확인할 수 있습니다.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.main = main;
var NumberClass = /** @class */ (function () {
    function NumberClass(id) {
        this.id = id;
        console.log(typeof id, typeof this.id);
    }
    NumberClass.prototype.toString = function () {
        return "".concat(this.id);
    };
    return NumberClass;
}());
function main() {
    var stringNumber = "124214";
    var numClass = new NumberClass(stringNumber);
    console.log(numClass.toString());
}
main();

JS에서는 더이상 타입체크를 하지 않기 때문에 불안전한 코드가 생겨버렸고 의도치 않은 동작 혹은 런타임 에러가 발생할 가능성이 생겼습니다.

이를 방지하기 위해 가장 중요한 것은 any를 사용하지 않는 것입니다.

만일 명시적으로 타입을 선언했다고 가정해봅시다.

파라미터로 사용된 stringNumber 변수에 명시적으로 타입을 선언했지만 해당 변수에 대입되는 변수의 타입이 any라면 이는 안전하지 않는 코드가 됩니다.

그렇다고 any를 아예 안쓸 수는 없을겁니다. 외부 API에 의해서 타입이 명시되어 있지 않을 수도 있고 갑자기 타입이 변경되는 등 타입이 모호할 경우가 있습니다.

이를 위해서 unknown 으로 대체할 수 있습니다.

unknown 타입은 TypeScript 3.0 에서 새롭게 출시된 any 대응 타입입니다.

unknown의 특징은 아래와 같습니다.

  • 자신과 any만 할당할 수 있습니다. → unknownany 타입 외의 타입(string, number, boolean, Function, object …)에서는 할당 불가능

그렇기 때문에 그 외 타입에 할당하기 위해서는 명시적으로 형 변환을 시켜줘야 합니다.
unknown 타입에 any 타입을 할당 후 number 변수에 할당하려 했지만 실패


이처럼 Type Checking 과 동시에 Error Handling을 할 수 있게 되어 안전한 코드가 되었습니다.

추가로 tsconfig 에서 noImplictAny 옵션과 eslint no-explicit-any 옵션을 활용하여 any 사용을 방지할 수 있습니다.

위와 다른 케이스로 Nest.js 에서 @Req, @Query,@Param 데코레이터를 이용하여 값을 불러올 때 마찬가지로 string 형 number 가 number로 타입 변환이 제대로 이루어지지 않을 때가 있습니다.

이럴 때 해결 방법 중 하나는 ValidationPipe의 trsnform 옵션을 사용할 경우 올바르게 타입 변환이 가능합니다.

profile
다양한 경험을 해보고자 하는 Backend-Engineer.

0개의 댓글