[TS] About TypeScript #2

hang_kem_0531·2022년 6월 22일
0

Typescript

목록 보기
2/3
post-thumbnail

타입을 미리 정하기 애매할 때 (union type, any, unknown)

Union Type

유니온 타입(Union Type)이란, 자바스크립트의 OR 연산자 (||)와 같이 A이거나 B이다 라는 의미의 타입이다.

function logText(text: string | number) {
  // ...
}

위 함수의 파라미터 text에는 문자열 타입이나 숫자 타입이 모두 올 수 있다. 그리고 할당하는 순간, 해당 파라미터의 타입은 string 또는 number 중 하나로 변한다. 이처럼 | 연산자를 이용하여 타입을 여러 개 연결하는 방식을 유니온 타입 정의 방식이라고 부른다.

Union Type의 장점

// any를 사용하는 경우
function getAge(age: any) {
  age.toFixed(); // 에러 발생, age의 타입이 any로 추론되기 때문에 숫자 관련된 API를 작성할 때 코드가 자동 완성되지 않는다.
  return age;
}

// 유니온 타입을 사용하는 경우
function getAge(age: number | string) {
  if (typeof age === 'number') {
    age.toFixed(); // 정상 동작, age의 타입이 `number`로 추론되기 때문에 숫자 관련된 API를 쉽게 자동완성 할 수 있다.
    return age;
  }
  if (typeof age === 'string') {
    return age;
  }
  return new TypeError('age must be number or string');
}

Union Type을 사용하면 타입스크립트의 이점을 살리면서 코딩할 수 있다.


Any Type

TypeScript에서 Any 타입은 어떠한 타입도 허용하는 타입이다. 그렇기 때문에 타입을 엄격하게 검사하고 처리하는 TypeScript에서는 치명적으로 작용할 수 있다. 만일 타입 관련 버그가 생길 경우에는 이를 추적하기가 어렵기 때문이다.

let name: any = 'kyeom';
name = 123;
name = undefined;
name = [];
// 오류가 발생하지 않는다.

Any Type 지양하기

any 타입에는 타입 안정성이 없다

let age: number;
age = '12';
// ~~~ '"12"' 형식은 'number' 형식에 할당할 수 없습니다.
age = '12' as any; // OK

위의 예제에서 age는 number 타입으로 선언되었지만, as any를 사용하면 string 타입을 할당할 수 있게 된다. Type checker는 선언에 따라 number type으로 판단할 것이고 이후에 혼돈은 걷잡을 수 없게 된다.

age += 1 ; // Runtime에서는 정상, age = '121';

any는 함수 시그니처를 무시해 버린다

함수를 작성할 때는 시그니처(호출하는 쪽은 약속된 타입의 입력을 제공하고, 함수는 약속된 타입의 출력을 반환)을 명시해야 한다. 그러나 any 타입을 사용하면 이런 약속을 어길 수 있다.

function caculateAge(birthDate: Date): number {
  // ...
}

let birthDate: any = '1990-01-19';
caculateAge(birthDate); // 정상

birthDate 매개변수는 string이 아닌 Date 타입이어야 한다. 하지만 any 타입을 사용하면 calculateAge의 시그니처를 무시하게 된다. 자바스크립트에서는 종종 암시적으로 타입이 변환되기 때문에 이런 경우 특히 문제가 될 수 있다. string 타입은 number 타입이 필요한 곳에서 오류 없이 실행될 때가 있고, 그럴 경우 다른 곳에서 문제를 일으키게 된다.

any 타입에는 언어 서비스가 적용되지 않는다

어떤 심벌에 타입이 있다면 타입스크립트 언어 서비스는 자동완성 기능과 적절한 도움말을 제공한다. 그러나 any 타입인 심벌을 사용하면 아무런 도움을 받지 못한다.

타입스크립트의 모토는 '확장 가능한 자바스크립트'이다. '확장'의 중요한 부분은 바로 타입스크립트 경험의 핵심 요소인 언어 서비스이다. 언어 서비스를 제대로 누려야 개발자의 생산성이 향상되게 된다.

any는 타입 설계를 감춰버린다.

애플리케이션 상태 같은 객체를 정의할려면 꽤 복잡하고, 객체 안에 있는 수많은 속성의 타입을 일일이 작성해야 하는데, any 타입을 사용하면 간단히 끝내버릴 수 있다.

하지만 any 타입을 사용하면 타입 설계가 불분명해지고, 설계가 잘 되었는지, 설계가 어떻게 되어 있는지 전혀 알 수 없다. 만약 동료 개발자가 코드를 검토해야 한다면, 동료 개발자는 애플리케이션의 상태를 어떻게 변경헀는지 코드부터 재구성 해봐야 한다. 그러므로 설계가 명확히 보이도록 타입을 일일이 작성하는 것이 좋다.


Unknown Type

Unknown Type 역시 any type과 동일하게 모든 값을 허용하지만, 할당된 값이 어떤 타입인지 알 수 없기 때문에 프로퍼티나 연산을 할 수 없다는 차이가 있다.

unknown 타입인 채로 값을 사용하면 오류가 발생한다. unknown인 값에 함수 호출을 하거나 연산을 하려고 해도 마찬가지이다. unknown 상태로 사용하려고 하면 오류가 발생하기 때문에, 적절한 타입으로 변환하도록 강제할 수 있다.

그렇기 때문에 unknown은 any 대신 사용할 수 있는 안전한 타입이다. 어떠한 값이 있지만 그 타입을 알지 못하는 경우이거나, 사용자가 타입 단언문이나 타입 체크를 사용하도록 강제하려면 any 대신 unknown을 사용하면 된다.

let	foo: unknown;

let object1: string = foo;
let object2: boolean = foo;
let object3: number = foo;

let foo: unknown;
foo[0];
foo - 1;
foo.data;


함수에 타입 지정하는 법 & Void 타입

함수틑 타입스크립트로 크게 다음 3가지 타입을 정의할 수 있다.

  • 함수의 파라미터(매개변수) 타입

  • 함수의 반환 타입

  • 함수의 구조 타입

함수의 기본적인 타입 선언

function sum(a: number, b:number): number {
  return a + b;
}

기존 자바스크립트 함수의 선언 방식에서 매개변수와 함수의 반환 값에 타입을 추가하였다. 이때 함수의 반환 값에 타입을 정하지 않을 때는 void 타입이라도 사용하는 것이 좋다.

함수의 인자

타입스크립트에서는 함수의 인자를 모두 필수 값으로 간주한다. 따라서, 함수의 매개변수를 설정하면 undefinednull이라도 인자로 넘겨야하며 컴파일러에서 정의된 매개변수 값이 넘어왔는지 확인한다. 이는 정의된 매개변수 외에는 추가로 인자를 받을 수 없다는 의미이기도 하다.

function sum(a: number, b: number): number {
  return a + b;
}
sum(10, 20); // 30
sum(10, 20, 30); // error, too many parameters
sum(10); // error, too few parameters

위와 같은 특성은 정의된 매개변수의 갯수 만큼 인자를 넘기지 않아도 되는 자바스크립트의 특성과 반대되는데, 이러한 특성을 살리고 싶다면 ?를 이용해서 아래와 같이 정의할 수 있다.

function sum(a: number, b?: number): number {
  return a + b;
}
sum(10, 20); // 30
sum(10, 20, 30); // error, too many parameters
sum(10); // 10
profile
Front-End Developer

0개의 댓글