아이템 33. string 타입보다 더 구체적인 타입 사용하기 #
string 타입의 범위는 매우 넓다.(“a”, “b”, “casdsad”, …)
다음은 string 타입이 남발된 타입의 예시이다.
interface Album {
artist: string;
title: string;
releaseDate: string; // 예를 들어, yyyy-mm-dd
recordingType: string; // 예를 들어, "live" 또는 "studio"
}
string 은 다음과 같은 단점이 있다.
예를 들어,
recordingType
에 “Live” 값이 들어가도, 타입 체커는 완벽하게 체크할 수 없다.releaseDate
에 “asdsad” 값이 들어가도, 타입체커는 완벽하게 체크할 수 없다.- 혹은 매개변수의 순서가 바뀌어도 (
releaseDate
위치에recordingType
값을 넣는다던가…)
다음과 같이 개선해볼 수 있다. #
type RecordingType = 'studio' | 'live';
interface Album {
artist: string;
title: string;
releaseDate: Date;
recordingType: RecordingType;
}
다음과 같은 이점이 있다.
- (타입을 명시적으로 정의함으로써) 다른 곳으로 값이 전달되어도, 타입 정보가 유지된다.
- 즉, 타입 정보를 계속 갖고간다.
- 타입을 명시적으로 정의하고, 해당 타입의 의미를 설명하는 주석을 붙여 넣을 수 있다.
- IDE 상에서 주석 및 타입 정보를 쉽게 확인 가능하다.
- keyof 연산자로 더욱 세밀하게 타입 체크가 가능하다.
아래는 추가적인 개선 예시이다.
// 개선 X
function pluck<T>(records: T[], key: string): any[] {
return records.map(r => r[key]);
// ~~~~~~~~ '{}' 형식에 인덱스 시그니처가 없으므로 요소에 암시적으로 'any' 형식이 있습니다.
}
// 개선
function pluck<T>(records: T[], key: keyOf T) {
return records.map(r => r[key]);
}
// 개선의 개선
function pluck<T, K extends keyof T>(records: T[], key: K): T[K][] {
return records.map(r => r[key]);
}
위(개선의 개선)와 같은 경우, 매개변수 타입이 정밀해진 덕분에 (IDE 단에서)자동완성 기능도 제공될 수 있다.
string 은 any와 비슷한 문제를 가지고 있다. #
무효한 값을 허용하고, 타입 간의 관계도 감춰버린다.
타입 체커를 방해하고, 실제 버그를 찾지 못하게 한다.
string의 부분 집합을 정의하는 것은, js에 타입 안정성을 크게 높인다.
요약 & 정리 #
- string 을 남발하여 선언된 코드를 피하자.
- 변수의 범위를 보다 정확하게 표현하자.
- string 타입보다는 리터럴 타입의 유니온을 사용할 수 있다.
- 객체의 속성 이름을 함수 매개변수로 받을 때는,
string
보다keyof T
를 사용하자.