본문 바로가기

Front-End: Web/TypeScript

[코딩애플] ts part 1-5. Narrowing & Assertion

반응형

타입 확정하기

function 내함수(x :number|string) {
    return x + 1; // 에러 발생
}
내함수(123);

x는 number도 string도 아닌 number| string, 즉 union type이다. 그래서 타입이 확정되지 않아서 연산이 되지 않아 에러가 발생한다 했다.

이처럼 **Type이 아직 하나로 확정되지 않았을 경우****Type Narrowing**을 써야 한다.

Narrowing

어떤 변수가 타입이 아직 불확실하다면, 꼭 if문 등으로 Narrowing 해줘야 조작이 가능하다.

  • Narrowing -> **타입을 하나로 정한다, 거른다는 의미**
function 내함수(x :number|string) {
    if (x의 타입이 string){ // Narrowing
        return x + '1';
    } else {
        return x + 1;
    }
}
내함수(123);

Narrowing으로 판정해주는 문법들

  1. **typeof** 변수
  2. 속성명 **in** 오브젝트자료
  3. 인스턴스 **instanceof** 부모

➡️ 그냥 현재 변수의 타입이 뭔지 특정지을 수 있기만 하면 다 인정해준다

1. typeof 연산자 (대표적인 Narrowing 방법)

  • 예제 1) - 위의 예제
function 내함수(x :number|string) {
    if (typeof x === 'string'){
        return x + '1';
    } else {
        return x + 1;
    }
}
내함수(123);
  • 예제2)
function 내함수(x :number|string) {
    let arr :number[] = [];
    arr[0] = x; // 에러 발생: 타입이 Union type이기 때문에 number[]에 넣을 수 없음.
}
내함수(123);

**⚠️(주의) if문을 썼으면 끝까지 써야 안전하다. else, else if 안쓰면 에러로 잡아줄 수도 있음**

function 내함수(x :number|string) {
    let arr :number[] = [];
    if (typeof x === 'number'){
        arr[0] = x;
    } else {
        ...
    }
    
}
내함수(123);

2. in 키워드

어떤 속성이 이 오브젝트에 있는지 확인 가능

3. instanceof

이 오브젝트가 저 오브젝트의 자식인지 확인 가능

assertion (타입 덮어쓰기)

if문 필요없음.

만약 Type Narrowing하기 귀찮다 하면 assertion을 쓰면 된다.

function 내함수(x :number|string){
    let array :number[] = [];
    array[0] = x; // ts에러 발생: number 타입만 들어올 수 있습니다
}

이때 assertion을 써보자.

function 내함수(x :number|string){
    let array :number[] = [];
    array[0] = x as number; // x의 type을 number로 덮어써주세요!
}

이렇게 하면 if문 필요없고 더 간편하다.

그러면 "개편하네 앞으로 자주 쓴다"하고 쓰면 회사 사수가 빠따를 칠거다.

빠따 안맞기 위한 assertion 문법의 용도

1. Narrowing 할 때 쓰기

union type에서 타입을 하나로 정할 때 쓴다.

let 이름 :string = 'kim';
이름 as number; // 에러 발생.
  • 타입을 a에서 b로 변경할 때 쓰는 게 아니다.
  • union type에 타입을 하나로 정할 때 사용하는 거다.

2. 무슨 타입이 들어올지 100% 확실할 때 쓰기

function 내함수(x :number|string){
	let array :nubmer[] = [];
    array[0] = x as number;
}
내함수(123);
내함수('123'); // 문자 넣어도 아무일 없음 (assertion 해놓으면 이런 버그 캐치 못함)

문자로 넣어도 **버그를 캐치하지 못한다**. 그래서 무슨 타입이 들어올지 100% 확실할 때만 사용해야 한다.

그래서 평소에 쓰지말고, 남이 짠 코드를 수정하거나, 왜 타입에러가 나는지 모르겠을 때 디버깅용 비상용으로 as 문법을 사용하도록 하자.

(+) 예전 as 문법

let 이름 :string = 'kim';
<number>이름

🍯 Tip: as문법이 유용한 이유

가끔 타입을 강제로 부여하는 기계를 하나 만들어쓰고 싶은 때가 있다.

그럴 때 함수에 데이터를 넣으면 as 타입명을 붙여서 return하는 함수를 만들어서 사용하면 된다.

type Person = {
    name : string;
}

function 변환기<T>(data: string): T {
    return JSON.parse(data) as T;
}
const jake = 변환기<Person>('{"name":"kim"}');

변환기라는 함수를 만들고 이 함수에 자료를 입력하면 as 키워드로 타입을 하나 붙여준다.

아직 배우지 않은 문법들이 있는데, 그냥 그렇구나~하고 느끼고 넘어가면 나중에 알게 된다!

(+)

코드짜다가 콘솔창에 변수 출력해보고 싶으면, html 파일에 ts로 작성한 파일 넣으면 된다.

  • ts 파일은 못넣으니까 변환한 js 파일을 html 파일에 넣어준다.

숙제

(숙제1)

숫자여러개를 array 자료에 저장해놨는데 가끔 '4', '5' 이런 식의 문자타입의 숫자가 발견되고 있습니다.

이걸 클리닝해주는 함수가 필요합니다.

**클리닝함수( ['1', 2, '3'] )** 이렇게 숫자와 문자가 섞인 array를 입력하면

**[1,2,3]** 이렇게 숫자로 깔끔하게 변환되어 나오는 클리닝함수를 만들어오고 타입지정까지 확실히 해보십시오.

모르는 부분은 구글검색해도 봐드림

➡️

function cleaning(arr :(number|string)[]) :number[] {
    return arr.map(v => v as number);
}

(숙제2) 다음과 같은 함수를 만들어보십시오.

let 철수쌤 = { subject : 'math' }
let 영희쌤 = { subject : ['science', 'english'] }
let 민수쌤 = { subject : ['science', 'art', 'korean'] }

지금 여러 변수에 선생님이 가르치고 있는 과목이 저장이 되어있습니다.

과목 1개만 가르치는 쌤들은 문자 하나로 과목이 저장이 되어있고

과목 2개 이상 가르치는 쌤들은 array 자료로 과목들이 저장되어있습니다.

철수쌤같은 선생님 object 자료를 집어넣으면

그 선생님이 가르치고 있는 과목중 맨 뒤의 1개를 return 해주는 함수를 만들어봅시다.

그리고 타입지정도 엄격하게 해보도록 합시다.

(동작예시)

만들함수( { subject : 'math' } )  //이 경우 'math'를 return
만들함수( { subject : ['science', 'art', 'korean'] } ) //이 경우 'korean'을 return
만들함수( { hello : 'hi' } )  //이 경우 타입에러 나면 됩니다 

Q. 이 자료가 array type 인지 어떻게 검사하냐고요? 구글에 물어보시면 됩니다.

➡️

function 함수(teacher :{subject: string | string[]}) :string {
    if (typeof x.subject === 'string') {
        return teacher.subject
    } else if (Array.isArray(teacher.subject)) {
        return teacher.subject[x.subject.length - 1];
    } else {
        return '없쪄'
    }
}
  • **Array.isArray(a)** : a가 array인지 아닌지 true/false로 반환
반응형