TypeScript 타입 정리

Basic Types

잘 모르는 타입들에 대한 설명

Array

배열 타입이다. 배열에 들어갈 내용을 일방적으로 선언 할 수 있다.

let list: number[] = [1,2,3];

제너릭을 사용하여 선언할 수도 있다.

let list : Array[number] = [1,2,3];

Tuple

Tuple 은 배열타입이나 여러가지 타입을 혼용할 수 있다. 단, 타입을 지정하여 해당 인덱스의 타입을 지정할 수 있다. 단, 설정한 인덱스를 넘어갈 경우 지정한 타입을 모두 적용가능하지 주의할 것.

예를 들자면

let x : [string, number];

x[2] = 3 //OK
x[2] = 'a' //OK

위와 같이 설정한 인덱스는 1까지이나 2와 3번째 인덱스에 숫자와 문자열이 둘다 들어갈 수 있다. 하지만

x[2] = true; //error

Boolean을 넣으면 에러가 나듯이 숫자와 문자열 이외의 타입의 경우 들어가지 않는다.

Enum

Enum은 숫자에 이름을 붙이는 것으로, 숫자에 의미를 부여할 수 있게 해준다.
예를 들자면

enum  Color {Red, Green, Blue}
let c : Color = Color.Green // -> 1

enum으로 선언하고 클래스처럼 Color로 변수에 타입을 입힐 수 있다.
Color에 있는 값들은 맨 처음값이 0으로 시작하며 각 변수들의 값은 변경이 가능하다.

enum Color {Red = 1, Green, Blue}
let c : Color = Color.Green // -> 2

또한 숫자만 불러오는 것이 아니라 문자열도 불러 올 수 있다.

let a : string = Color[2] // 'Green'

Any

모든 값을 집어넣을 수 있는 타입이다. 라이브러리를 넣어야 할 경우 어떤 값이 들어갈 지 모르기 때문에 사용가능하다.

let notSure : any = 4;
notSure.ifItExists(); //OK
notSure.toFixed(); //OK because 4 has this methods. but if it isn't number it will make error

let prettySure: Object = 4; // Object means everything can be allowed here because javascript's all things are Object 
prettySure.toFixed(); //error occurs because Object itself doesn't have number object methods.

Object 타입을 쓸 수 있긴 지만 특정 object의 method를 사용할려고 하면 error가 난다. 타입 자체는 모든 타입이 object이기 때문에 error를 발생시키지 않지만 Object의 method는 오직 Object 가 가지고 있는 method만 사용 가능하다.

Void

아무런 타입을 가지지 않아야 할 경우 지정해야 할 타입. 함수에는 유용하나 변수를 선언할 때는 유용하지 않다. 왜냐하면 변수에 void를 사용할 경우에 undefined와 null을 모두 사용할 수 있기 때문이다.

function warnUser() : void {
    alert('this is my warning message'); 
    //no return -> void
}

위의 함수는 undefined는 반환할 수 있지만 null은 반환할 수 없게 되어 있다.

let a : void = undefined | null //--strictNullChecks 가 tsconfig.json에 설정되어 있을 경우에는 null이 안들어간다. strict를 true로 해도 동일한 결과를 얻을 수 있다. 모든 strict를 활성화 시키기 때문이다.

변수에는 둘다 들어간다. 그렇기 때문에 구분하기가 어렵다.

Null and Undefined

null과 undefined는 모든 객체들의 하위버전이라 number에도 undefined가 들어가도 이상하지 않다. (–strictNullChecks 가 tsconfig.json에 꺼져 있을 경우에 해당한다. 그렇기 때문에 strictNullCheck 를 키는 것을 추천한다고 쓰여있다.)

let a : number = undefined //number 하위에 undefined가 있어 들어갈 수 있다. --strictNullChecks 설정을 킬 경우 에러 발생

하지만 void에는 위에서 설명 했듯이 null 과 undefined 타입만 할당 가능하다.

Never

어떤 다른 타입도 Never에 사용 불가능하며 오로지 exception과 같이 throw되는 함수에 주로 사용한다. never에는 undefined, null, any조차 할당이 불가능하다.
예시로는 아래와 같다.

//never를 리턴하는 함수는 닿을 수 없는 프로그램의 끝을 가져야 한다.
function error(message:string) : never {
    throw new Error(message);
}

//Inferrred return type is never
function fail() {
    return error('Something failed');
}
//never를 리턴하는 함수는 닿을 수 없는 프로그램의 끝을 가져야 한다.
function infiniteLoop() : never {
    while(true);
}
//never는 never에 할당할 수 없다. never는 사실상 프로그램의 종료를 의미한다.
let a: never = function returnNever() : never {
    throw new Error('some kind of error');
} 

Type 변경

예제를 보자

let someValue : any = "this is a string";

let strLength : number = someValue.length; // compile error 가 뜬다. 어떤 타입인지 모르는데 length를 썼기 때문이다.

처음에 선언한 someValue는 any로 컴파일 되는데 밑에서 someValue는 length field를 사용하였다. 컴파일러는 someValue가 length field가 있는지 없는지 알 수 없기 때문에 컴파일 에러가 뜬다. 비록 any에 string 값이 들어갔더라도 말이다.

하지만 사용자가 타입을 직접 캐스팅 할경우 컴파일러는 해당 변수를 string으로 본다.

let someValue : any = 'This is a string'

let strLength : number = (<string>someValue).length //error가 나지 않는다.

//또는 (someValue as string).length로 사용도 가능하다.
//as를 사용하기를 추천한다. jsx에서는 제네릭이 안된다고 한다.

컴파일러는 someValue를 string으로 보고 someValue가 실제 무엇이 있는지는 확인하지 않는다는 점에 주목해야 한다. 즉, 타입의 변경에 대한 책임은 오로지 사용자에게 있으며 컴파일러는 someValue의 값에 무엇이 들어있는지는 확인하지 않고 오로지 someValue 가 string이라 판단하고 length field가 있다고 판단한다.

해당 변수가 무엇인지 확신할 수 있을 때 타입을 캐스팅해야한다. 컴파일러는 알수 없을테니 말이다.

참고 : number를 string으로는 캐스팅 할 수 없다.

1개의 좋아요