any, unknown, never

Changhan·2025년 1월 27일

Typescript

목록 보기
17/29

이번 포스팅에서는 any, unknown, never 타입에 대해 조금 더 알아보자.

any

앞에서 배운 any 타입을 다시 정리하자면 any 타입은 어떠한 값도 될 수 있는 타입이다.

let num: number;
number = 10;

이 num 변수에 문자열 전용 함수인 toUpperCase를 사용할 수 없다. 하지마 여기서 num 변수를 string으로 캐스팅을 하게 되면 문자열 전용 함수를 사용할 수 있는 것처럼 보인다.

num.toUpperCase(); // X
(num as string).toUpperCase();

이 코드는 타입스크립트 코드 상에서는 문제가 없다. 타입스크립트는 결국 최종적인 실행은 자바스크립트로 된다. 따라서 캐스팅은 자바스크립트에서는 없는 코드이기 때문에 실행 시 에러를 발생시킬 것이다.
그래서 중요한 것은 any를 마음대로 남발해서는 안된다!!

함수에서의 any

const multiple = (x: number, y: number) => {
  return x * y;
};
let arg1: any = '태연';
let arg2: any = true;

multiple(arg1, arg2); // 에러가 안남
multiple('태연', true); // 이렇게 되는 것이 정상

arg1, arg2를 any 타입으로 선언을 하고, 이 두 변수를 함수의 인자로 넣으면 에러가 발생하지 않는다.
하지만 인자에 직접적으로 값을 넣으면 에러가 발생한다. any로 캐스팅이 되면 어떠한 값도 인자로 넣을 수가 있게 된다. 그래서 이 또한 any의 좋지 않은 예시다.

객체에서의 any

객체에서의 any는 어떤 문제가 있는지 알아보자.

let taeyeon: any = { name: '태연', age: 32 };
console.log(taeyeon.name);
console.log(taeyeon.age);

객체를 any 타입으로 선언하게 되면 객체의 프로퍼티를 가져올 때 자동완성이 되지 않는다. 타입스크립트가 객체에 프로퍼티가 있다는 것을 알지 못하기 때문이다.


unknown

let anyValue: any;
anyValue = 1;
anyValue = true;
anyValue = '태연';
anyValue = undefined;
anyValue = null;
anyValue = [];
anyValue = {};

let unknownValue: unknown;
unknownValue = 1;
unknownValue = true;
unknownValue = '태연';
unknownValue = undefined;
unknownValue = null;
unknownValue = [];
unknownValue = {};

any와 unknown은 어떤 타입의 값을 할당할 수 있는 공통점을 가지고 있다.

any와 unknown의 차이

let anyType: any = anyValue;
let unknownType: unknown = anyValue;
let booleanTeyp: boolean = anyValue;
let arrayType: string[] = anyValue;
let objectType: {} = anyValue;
let nullType: null = anyValue;
let undefinedType: undefined = anyValue;

any 타입으로 선언된 변수는 어떤 타입에도 할당이 가능하다.

let anyType: any = unknownValue;
let unknownType: unknown = unknownValue;
let booleanTeyp: boolean = unknownValue; // error
let arrayType: string[] = unknownValue; // error
let objectType: {} = unknownValue; // error
let nullType: null = unknownValue; // error
let undefinedType: undefined = unknownValue; // error

unknown 타입으로 선언된 변수는 any, unknown 타입에만 할당이 가능하고, 나머지 타입에는 할당이 불가능하다.


anyValue.toUpperCase();
anyValue.name;

위의 코드는 실제로 자바스크립트로 컴파일된 후 에러가 발생하거나 undefined가 나오지만 타입스크립트에서는 정상적인 것처럼 보인다.

unknownValue.toUpperCase(); // error
unknownValue.name; // error

하지만 undefined의 경우 타입스크립트의 코드 상에서 바로 에러가 보이는 것을 확인할 수 있다.

union, intersection에서의 차이

type uOrString = unknown | string; // type: unknown
type uOrBoolean = unknown | boolean; // type: unknown
type uOrNumber = unknown | number; // type: unknown
type uOrAny = unknown | any; // type: any
// 유니언에서는 unknown이 모든 타입을 다 흡수하는데 any 타입일 때만 any 타입에 흡수가 된다.

type uAndString = unknown & string; // type: string
type uAndBoolean = unknown & boolean; // type: boolean
type uAndNumber = unknown & number; // type: number
type uAndNull = unknown & null; // type: null
type uAndAny = unknown & any; // type: any
// 인터섹션에서는 반대로 unknown이 any를 포함한 다른 모든 타입에 흡수가 된다.

union에서는 unknown 타입이 모든 타입을 다 흡수하지만, any 타입과의 조합일 때만 any 타입에 흡수가 된다.
intersection에서는 unknown 타입이 모든 타입에 전부 흡수가 된다.

unknown 타입의 연산

let number1: unknown = 10;
let number2: unknown = 20;

number1 - number2; // X
number1 / number2; // X

number1 === number2; // O
number1 == number2; // O
number1 !== number2; // O
number1 != number2; // O

unkonwn 타입끼리의 사칙연산은 불가능하다. unknown 타입이 알 수 없는 타입이기 때문이다. 하지만 논리연산은 가능하다.


never

never 타입이 형성되는 경우를 알아보자.

// 1. 함수에서 에러를 던질 때
function throwError(): never {
  throw Error();
}

// 2. 무한 루프
function Loop(): never {
  // while(true) {}
}

// 3. 존재할 수 없는 인터섹션
type StringAndNumber = string & number;


let neverType: never = 10;
let neverType: never = true;
let neverType: never = null;

never 타입은 한 마디로 일어날 수 없는 상황이다라는 것을 기억하자.


후기

내용은 딱히 어려운 것이 없었지만 헷갈릴 수 있는 이런 타입들을 조합했을 때 어떤 결과가 나오는지 아는 것은 굉장히 중요한 것 같다.

0개의 댓글