개발/typescript

타입스크립트 기초 문법 - 타입 추론, 타입 단언, 타입 좁히기

모그 2023. 12. 26. 09:34

1.타입 추론

타입 추론이 되는 경우

  • 초기값이 설정된 변수와 객체

    let num1 = 100; // number type으로 추론
    let str1 = "type" // string type으로 추론

    let object1 = {
        name: "이름", // string으로 추론
        age: 100, //number으로 추론
        skill : {
            kill: "test" //string으로 추론
        }
    }
 

 

  • 객체와 배열의 구조분해할당

    let object1 = {
        name: "이름",
        age: 100,
        skill : {
            kill: "test"
        }
    }

    let {name, age, skill} = object1; //각각 string,number,string으로 추론

    let [one,two,three] = [true,122,"문자"] //각각 boolean,number,string 으로 추론
 

 

  • 함수의 반환값

    function foo(){ //number type으로 추론
        return 12345;
    }
 

 

  • 함수의 매개변수에 기본값이 설정된 경우

    function foo(value = "test"){ // value는 string type으로 추론
        return 12345;
    }
 

 

타입 추론 안되는 경우

  • 함수 파라미터가 타입 정의되어있지 않은 경우

    function foo(value){ // 오류
        return 12345;
    }

 

 

암시적으로 any타입이 추론되는 경우

  • 초기값 설정 안한 변수

그 후에 어떤 값을 할당하느냐에 따라 타입이 변화한다.


    let type; // any
    type = 100 // any -> 아직 변수에 100이 담기지 않은 상태, 줄바꿈이 되어야 담긴다
    type; // number
    type ="test" //any
    type; //string
    type = true //any
    type; //boolean
 

 

 

const 상수


  let unm1 = 100; //number type으로 추론
  const num2 = 100 //100으로 추론
 

 

const는 초기화 할 때 설정한 값을 변경할 수 없기때문에 가장 좁은 타입으로 추론된다.

 

 

2. 타입 단언

  • 특정 값을 원하는 타입으로 단언할 수 있다.
type Test = {
    name:string;
    age:number;
}

let obj:Test = {}


obj.name="이름";
obj.age=100;

 

name과 age 프로퍼티 두 개를 갖는 타입으로 타입을 정의했지만 

객체 자체는 빈 값으로 초기화한다면 오류메시지가 뜬다.

 

이 때 

let obj = {} as Type

으로 타입단언을 이용하면 오류가 사라진다.

 

  • 초과 프로퍼티에 의한 오류 해제 가능
type Test = {
    name:string;
    color:string;
}


let dog:Test = {
    name:"멍멍",
    color:"점박",
    breed:"믹스"
} as Test

 

다음과 같은 초과 프로퍼티 상황에도 타입단언을 이용해서 눈속임할 수 있다.

 

  • 타입 단언 사용조건

값과 타입 서로가 서로의 슈퍼 혹은 서브타입이어야한다.

예를 들어 


    let val01 = 100 as string //오류
 

 

  • 다중 단언

위와 같은 경우에도 꼼수가 하나 있는데 바로 타입 단언을 여러 번 하는 것도 가능하다.


    let num = 10 as any as string
 

 

이렇게 두 번에 걸쳐 타입선언을 하면 number타입으로 정의된 변수를 string타입으로 선언할 수도 있지만

나중에 오류 발생 가능성이 높아 주의해야 함

 

  • const 단언

const 타입으로 단언하면 변수를 const로 선언한 것과 비슷하다.


    let num = 10 as const //num의 타입은 10이 된다
    num = 100; //오류

    let cat = {
        name:"야옹" //모든 프로퍼티는 읽기전용인 readonly가 된다
    } as const
    cat.name="냐옹" //오류

 

 

오류가 발생하는 부분은 터미널에 이렇게 표시된다.

 

  • Non Null 단언

뒤에 !  를 붙이면 이 값은 undefined/null이 아닐 것으로 단언할 수 있다.

type Post = {
    title:string;
    author?:string
}
let post:Post = {
    title:"제목"
}
cosnt test:number = post.author!.length;

 

Post타입에는 title과 author가 있지만 author는 있을 수도, 없을 수도 있는 프로퍼티이다.

이런 경우 맨 아랫줄은 오류가 발생하는데 이 때 Non Null단언 활용 가능

 

3.타입 좁히기

 

function foo (val: number | string) { }

에서 파라미터는 number타입이 될 수도, string 타입이 될 수도 있다.

function foo (val: number | string) {
    val.toFixed();
    val.toUpperCase();
}

파라미터가 숫자일지 문자일지 모르는 상태이기때문에 실행문은 모두 오류가 발생한다.

이 때 타입 좁히기를 사용할 수 있음

 

3-1) typeof ===

function foo (val: number | string) {
    if( typeof val === "number" ) {
        val.toFixed();
    }
else if( typeof val === "string" ) {
    	val.toUpperCase();
    }
}

 

3-2) instanceof

이번엔 내장 클래스 타입을 보장할 수 있는 타입가드이다.

function foo (val: number | string | Date) {
    if( typeof val === "number" ) {
    	val.toFixed();
    } else if( typeof val === "string" ) {
        val.toUpperCase();
    } else if (val instanceof Date) {
    	console.log(val)
    }
}

instanceof 타입가드는 내장 클래스, 직접 만든 클래스에만 사용 가능하다.

 

3-3) in 타입가드

type Test = {
    test1: string;
    test2: number;
}

function foo(val : number | string | Test) {
    if("test2" in val) {
    	console.log(`테스트2 : ${test2}`)
    }
}

 

test2라는 프로퍼티가 val 안에 있다면 콘솔창에 텍스트를 출력한다.