Narrowing 할 수 있는 방법 더 알아보기
typeof 연산자로는 부족하다
Narrowing할 때 typeof 연산자 갖다쓰면 된다 했다. 근데 가끔은 typeof 키워드로 할 수 없는 Narrowing 상황들이 있다.
null & undefined -> 타입체크하는 경우 매우 잦음
그 전에 테그닉 하나만 배우고 가자.
실제 코드를 짤 때 'undefined'라는 타입을 체크하는 경우가 엄청 많다. 예로 들어서 함수를 하나 만들었다 하자. 이 함수는 string 혹은 undefined다.
function 함수(a :string | undefined){
}
이때 a를 그냥 쓰면 안된다. if 문을 써서 a가 string인지, undefined인지 체크해야 한다. 근데 이게 귀찮아서 대신 typeof 연산자를 쓴다 했다.
function 함수(a :string | undefined){
if(typeof a === 'string'){
} else {
}
}
이렇게 하면 undefined 경우를 체크할 수 있다. 근데 이걸 하나로 줄일 수 있다.
1. && 연산자로 null & undefined 타입체크하기
if (a && typeof a === 'string') { ... }
이렇게 하면 이제 undefined인지도 한 번에 Narrowing할 수 있다.
case 1. a가 undefined면,
➡️ 조건식 전체가 undefined가 남는다. 그래서 if문 조건식이 만족하지 않아서 실행되지 않는다.
case2. a가 string 타입이면
➡️ 우측에 있는 조건식이 실행된다. 조건식(typeof a === 'string')을 실행하면 true가 남는다.
즉,
- a가 undefined면 if문 실행 X
- a가 string이면 if문 실행 O
이것도 일종의 Narrowing으로 볼 수 있다. 일케 하면 undefined와 null 타입도 체크할 수 있다. if문 쓰기 귀찮으면 이거 쓰자.
근데 이게 익숙하지 않다? 하면 안쓰는 것도 좋다. 차라리 if/else 쓰는게 명확하고 좋을지도.
in 키워드로 objec narrowing 가능
typeof 연산자는 number, string, boolean, object 이런 식으로만 판정가능
Fish | Bird 타입만 들어올 수 있는 함수가 있다.
type FIsh = {swim :string}
type Bird = {fly :string}
function 함수(animal :Fish | Bird){
animal.swim // Error!
}
animal 변수를 조작하려고 animal.swim을 치면 에러가 난다. 못한다. 왜냐면 animal 변수는 아직 애매해서 swim을 포함할 수 없을 수도 있다. 그래서 Narrowing을 해줘야 한다.
type FIsh = {swim :string}
type Bird = {fly :string}
function 함수(animal :Fish | Bird){
if(typeof animal === Fish) {
animal.swim // Error!
}
}
Fish라고 typeof 연산자를 해주면 에러가 발생한다. 왜냐하면 typeof 연산자는 number, string, boolean, object, bigint, function, symbol, undefined, ... 등 자동완성되는 타입들만 판정할 수 있기 때문이다.
이때 쓸 수 있는게 in 키워드다!서로 배타적인 속성을 가지고 있는 타입들이 있다. Fish 타입은 swim 속성명을 가지고 있고, Bird 타입은 fly 속성명을 가지고 있다. 서로 가진 속성명이 다르다.
그런 오브젝트를 구분하고 싶을 때 in 키워드를 쓰면 된다.
속성명 in 오브젝트자료
왼쪽에 있는 속성명이 오른쪽에 있는 오브젝트에 들어가 있는지 알 수 있다. 이걸 코드에 응용해보면,
type FIsh = {swim :string}
type Bird = {fly :string}
function 함수(animal :Fish | Bird){
if('swim' in animal) { // Fish 타입인지 검사가능
animal.swim;
}
}
유사하게 fly 속성으로 'Bird' 타입인지 검사 가능하다.
⭐서로 가진 속성명이 다르다면 in 써보자!
3. instanceof 연산자로 object narrowing 가능
오브젝트 instanceof 부모class
왼쪽 오브젝트의 부모가 오른쪽 부모가 맞는지 true/false 반환된다.
**object 두개가 비슷하면 부모 class가 누군지 물어봐서 narrowing 가능하다.**
예제를 보자면 이렇게.
let 날짜 = new Date();
if (날짜 instanceof Date){
...
}
4. object 타입마다 literal type 만들어두면 narrowing 편리해짐
object 타입이 둘다 비슷하게 생겼는데 이런 경우엔 narrowing을 어떻게 하나?
type Car = {
wheel : '4개',
color : string
}
type Bike = {
wheel : '2개',
color : string
}
function 함수(x :Car | Bike){
if(x가 Car 타입이냐?)
}
in 키워드? instanceof? 못하지!
- in 쓰려면 배타적인 속성을 찾아야한다. 근데 둘이 속성명이 같다.
- instanceof? 둘 다 부모가 없다. 그래서 쓸 수 없다.
이렇게 비슷한 오브젝트 두개 타입을 구분해야 한다? 근데 애초에 타입을 하나로 합치지 왜 비슷한 타입을 따로 만들었나.. 근데 굳이굳이 구분을 해야한다면.
**비슷한 object 타입일 경우, literal type을 강제로 만들어두면 나중에 도움된다.**
wheel은 무조건 unique한 string이 들어올 수 있다. 이 literal type을 이용하면 구분할 수 있다. 이것도 unique해서 배타적이기 때문.
이때 if문을 이렇게 작성할 수 있겠다.
function 함수(x :Car | Bike){
if(x.wheel === '4개'){ // 이 경우, x변수는 Car 타입임
console.log('x는 Car타입이에요')
}
}
⭐비슷한 object 타입이 많다! 그러면 literal type(고정된 값)을 넣어보자
Recap
논리적으로 이 타입인지 특정지을 수 있으면 narrowing으로 인정해줌. 자신있게 해보자.
'Front-End: Web > TypeScript' 카테고리의 다른 글
[코딩애플] ts part 2-4. public & private (0) | 2022.10.23 |
---|---|
[코딩애플] ts part 2-3. never type (0) | 2022.10.23 |
[코딩애플] ts part 2-1. rest parameter & destructuring (0) | 2022.10.22 |
[코딩애플] ts part 1-11. interface (0) | 2022.10.22 |
[코딩애플] ts part 1-10. class types (0) | 2022.10.22 |