반응형
정제
TypeScript는 심벌 수행(symbolic execution)의 일종인 흐름 기반 타입 추론을 수행합니다.
즉, 타입 검사기는 typeof, instanceof, in 등의 타입 질의뿐 아니라, 마치 프로그래머가 코드를 읽듯 if, ?, ||, switch 같은 제어 흐름 문장까지 고려하여 타입을 정제(refinement)합니다.
이는 타입 검사기에 제공되는 아주 유용한 기능으로 오직 일부의 언어에서만 지원합니다.
예를 살펴보겠습니다.
TypeScript에 CSS 규칙을 정의하는 내장 API가 있고 동료 개발자가 HTML 요소의 너비(width)를 설정하려 한다고 가정해 봅시다.
너비를 전달하면 이를 파싱하고 검증할 것입니다.
먼저 CSS 문자열을 값(value)과 단위(unit)로 파싱 하는 함수를 구현합니다.
// 문자열 리터럴 유니온으로 CSS 단위가 가질 수 있는 값을 설명
type Unit = 'cm' | 'px' | '%'
// 지원하는 단위를 나열
let units: Unit[] = ['cm', 'px', '%']
// 지원하는 단위 각각을 확인하고 일치하는 값이 없으면 null 반환
function parseUnit(value: string): Unit | null {
for(let i = 0; i < units.length; i++){
if(value.endsWith(units[i])){
return units[i]
}
}
return null
}
parseUnit을 이용해 사용자가 전달한 width 값을 파싱 할 수 있습니다.
width는 숫자일 수도 있고, 아니면 단위가 포함된 문자열이나 심지어는 null 또는 undefined일 수도 있습니다.
이 예제에선 타입 정제를 여러 번 활용합니다.
// 문자열 리터럴 유니온으로 CSS 단위가 가질 수 있는 값을 설명
type Unit = 'cm' | 'px' | '%'
// 지원하는 단위를 나열
let units: Unit[] = ['cm', 'px', '%']
// 지원하는 단위 각각을 확인하고 일치하는 값이 없으면 null 반환
function parseUnit(value: string): Unit | null {
for(let i = 0; i < units.length; i++){
if(value.endsWith(units[i])){
return units[i]
}
}
return null
}
type Width = {
unit: Unit
value: number
}
function parseWidth(width: number | string | null | undefined): Width | null {
// width가 null이거나 undefined면 일찍 반환
if(width == null){ // ①
return null
}
// width가 숫자면 픽셀로 취급
if(typeof width === 'number'){ // ②
return {unit: 'px', value: width}
}
// width로부터 단위 파싱
let unit = parseUnit(width)
if(unit){ // ③
return {unit, value: parseFloat(width)}
}
// 이 외의 경우엔 null 반환
return null // ④
}
- TypeScript는 영리해서 JavaScript에서 null에 느슨한 동질성 확인을 수행하면 null과 undefined 모두 true를 반환한다는 사실을 알고 있습니다. width가 null이나 undefined라면 이 단계에서 함수가 반환될 것이므로, 반환되지 않고 코드를 계속 실행한다는 것은 width의 타입이 number | string임을 의미합니다.(null이나 undefined일 수 없음!)
- 런타임에 어떤 값의 타입을 확인할 때 typeof 검사를 사용하는데, TypeScript는 컴파일 타임에도 typeof를 활용합니다. if문에서 이 검사가 통과되는지에 따라 TypeScript는 width가 숫자이거나 아니면 마지막 남은 타입인 문자열인지 알 수 있습니다.
- parseUnit은 null을 반환할 수 있으므로, 정말 null을 반환하는지 알아보기 위해 결과가 참인지 확인합니다. TypeScript는 unit이 참이라면 이 if문에 의해 Unit 타입임이 확실해지고 거짓이라면 null 타입으로 판명됩니다.(Unit | null에서 정제됨!)
- 마지막으로 null을 반환합니다. 사용자가 width 인수로 문자열을 전달했지만 지원하지 않는 단위를 포함하고 있는 상황입니다.
반응형
'👶 TypeScript' 카테고리의 다른 글
철저 검사(Exhaustiveness Checking)라 불리는 종합성(Totality) (0) | 2023.01.19 |
---|---|
정제 - 차별된 유니온 타입 (0) | 2023.01.19 |
타입 넓히기 - 초과 프로퍼티 확인 (0) | 2023.01.18 |
타입 넓히기 - const 타입 (0) | 2023.01.18 |
할당성(assignability) (0) | 2023.01.18 |