Tip-04. 주의할 것들

사용하지 말아야 할 것들

열거형(enum)

아래 코드처럼 값으로 숫자가 들어가면 괜찮지만, 숫자 외의 다른 값이 들어가면 의도와 다르게 동작할 수 있다.

enum Flavor {
  VANILLA = 0,
  CHOCOLATE = 1,
  STRAWBERRY = 2,
}

아래와 같은 문자열 열거형은 덕 타이핑이 아닌 명목적 타이핑을 사용한다.

enum Flavor {
    VANILLA = 'vanilla'
    CHOCOLATE = 'chocolate'
    STRAWBERRY = 'strawberry'
}

let flavor = Flavor.CHOCOLATE // 타입이 Flavor
flavor = 'strawberry'; // 덕타이핑이면 Flavor에 포함되므로 에러가 안뜨곘지만, 명목적 타이핑이기 때문에 에러가 뜬다.

그리고 무엇보다... Rollup과 같은 번들러에서 트리쉐이킹이 되지 않는다.
즉, 최적화가 제대로 이루어지지 않는다.
enum 대신 union type이나 const enum을 사용하자.
union type은 타입스크립트를 쓴다면 수도 없이 쓸테니 const enum의 예제만 작성한다.
가능하면 union type을 사용하자.

const enum MOBILE_OS {
  IOS = 'iOS',
  ANDROID = 'Android',
}
const ios = MOBILE_OS.IOS;

매개변수 속성

아래와 같이 사용할 수 있는 것을 매개변수 속성이라고 한다.
매개변수 속성은 런타임시에 실제로 사용되는 코드이기 때문에 번들될 때 코드가 늘어난다.
게다가 가독성도 그닥인듯... 일관성 있게 클래스 변수를 직접 선언해주자.

class Person {
  constructor(public name: string) {}
}

네임스페이스와 트리플 슬래시 임포트

namespace 키워드나 /// 임포트 사용을 자제하자.
둘 다 호환성을 위해 남아 있을 뿐이다. ES2015 스타일의 모듈(import, export)를 사용하자.
(namespace는 라이브러리들 까보면 가끔 보이는데... 트리플 슬래시는 본 적 없는것 같다.)
새로 개발하는데 이것들을 쓴다? 아 이건 좀 ㅋㅋㅋ;

namespace foo {
  function bar() {}
}

/// <reference path="other.ts"/>
foo.bar();

데코레이터

데코레이터 패턴! 스프링에서 어노테이션이라는 이름으로 많이 사용해봤던 패턴이다.
2020.04.27일자 기준으로 tc39에 stage 3에 위치해 있다.(관련 repo 링크open in new window)
빠르면 내년, 늦으면 내후년에 표준으로 합류할 가능성이 매우 높지만... 어디까지나 가능성일 뿐이다.
비표준이 될 수도 있으니 일단은 사용을 자제하자.


주의할 것들

객체 순회

덕 타이핑으로 인해 객체를 순회하는 for in 문법이 제대로 먹히지 않는다.
프로토타입 오염이 되어있을 경우 우리가 작성한 속성 외에 다른 값도 순회에 포함될 수도 있기 때문이다.

const obj = {
  one: 'uno',
  two: 'dos',
  three: 'tres',
};
for (const k in obj) {
  const v = obj[k]; // 여기서 에러
}
// 에러 메세지
/*
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ one: string; two: string; three: string; }'.
  No index signature with a parameter of type 'string' was found on type '{ one: string; two: string; three: string; }'
*/

객체를 순회하며 키 값을 얻고 싶다면, keyof를 이용해서 키에 정확한 타입을 지정해주거나
Object.entries(obj)와 같이 배열로 만들어줘서 for of를 사용하자.

const obj = {
  one: 'uno',
  two: 'dos',
  three: 'tres',
};
for (const [k, v] of Object.entries(obj)) {
  console.log(k, v);
}

정보를 감추기 위해 private 사용하지 말기

어차피 private은 런타임에서 사라진다. 심지어 컴파일 시점에서도 단언문을 이용하면 접근이 가능하다.
정말로 정보를 감추고 싶으면 클로저를 사용하자.

개인적인 팁

array.find<T>()와 같은 함수는 T타입의 값 혹은 undefined를 반환한다.
만약 find로 값을 찾지 못했을 때 런타임을 종료시켜야 한다면... 매번 예외 처리를 해주어야 할 것이다.
이런것들은 그냥 모듈화해서 사용자 정의 함수로 만들어버리자. 그게 속 편하다.

Last Updated: