타입스크립트에서 타입을 명시적으로 나타낼 때는 변수명 뒤에 : {타입}을 붙여서 나타내면 된다.
let a : number = 1
let b : string = "hello"
let c : boolean = true
let d : number[] = [1, 2, 3, 4]
let e : [string, number, boolean] = ["hello", 5, true]
let f : any[] = [1, 2, "3"]
any를 사용하면 어떤 타입이든 들어갈 수 있다. 그러므로 any를 사용하면 타입스크립트가 아닌 자바스크립트와 같다고 생각하면 된다. 즉, any를 사용하는 것은 타입스크립트의 장점을 모두 포기하는 것이기 때문에 권장되지 않는다.
let g : unknown
만약 API로부터 응답을 받는데 그 응답의 타입을 모른다면 unknown타입을 사용할 수 있다. g의 타입이 unknown이기 때문에 g를 사용하려면 g의 타입을 확인하고 사용하도록 만든다. let g2 = g + 1 이렇게 바로 사용할 수 없다는 것이다.
let g : unknown
if(typeof g === 'number'){
let g2 = g + 1
}
if(typeof g === 'string'){
let g2 = g.toUpperCase()
}
이렇게 g의 타입을 확인한 후에 사용하면 된다.
타입 앞에 readonly를 붙이면 읽기 전용으로만 사용할 수 있도록 지정할 수 있다.
let d : readonly number[] = [1, 2, 3, 4]
여기에 number.push(5)와 같은 것은 이제 사용할 수 없게 된다.
let e : readonly [string, number, boolean] = ["hello", 5, true]
여기에도 e[0] = "hi"를 시도하려고 하면 오류가 발생하게 된다.
사실 타입스크립트에서 변수를 선언하는 방법은 두가지가 있다. 먼저 위에서 보았듯이 타입을 명시적으로 나타내주는 방법이다.
let a : string = "hello"
또는 타입스크립트가 변수의 타입을 추론하게 할 수도 있다.
let a = "hello"
타입스크립트가 a를 string 타입으로 자동으로 추론한다.
자바스크립트처럼 이렇게 선언된 a에 number와 같은 다른 자료형을 넣는 것은 이제 불가능하다.
Object를 선언할 때도 타입을 적어주고 값을 넣어주면 된다.
const cafe = {
name: string,
} = {
name: "starbucks"
}
그러나 만약 있을 수도 있고 없을 수도 있는 discount라는 것을 cafe 객체에 추가하려면 어떻게 될까?
이렇게 변수명 뒤에 ?를 붙이면 된다. discount의 타입은 'number | undefined'가 된다.
const cafe = {
name: string,
discount?: number
} = {
name: "starbucks"
}
그러므로, cafe.discount를 활용할 때는 cafe.discount가 존재하는지 확인하면서 활용하면 된다.
if(cafe.discount && cafe.discount > 10){
......
}
이렇게 카페 여러 개를 선언해야 한다면 중복되는 코드가 발생할 수 있다.
const cafeStarbucks = {
name: string,
discount?: number
} = {
name: "starbucks"
}
const cafeTwosome = {
name: string,
discount?: number
} = {
name: "twosome"
}
이때 alias를 이용하여 중복되는 코드를 줄일 수 있다.
type {별칭명}으로 타입을 선언해주면 된다. 별칭명은 대문자로 시작한다.
즉, Cafe라는 타입을 내가 임의로 만든 것이다.
type Cafe = {
name: string,
discount?: number
}
const cafeStarbucks : Cafe = {
name: "starbucks"
}
const cafeTwosome : Cafe = {
name: "twosome"
}
아래와 같이 일반적인 타입도 원하는 대로 별칭을 붙일 수도 있다.
type CafeName = string
const starbucks : CafeName = 'starbucks'
타입을 원하는 값들만 가능하도록 설정할 수도 있다. 이렇게 CafeName 타입의 변수들은 'starbucks' 또는 'twosome'만 가질 수 있도록 할 수 있다.
type CafeName = 'starbucks' | 'twosome'
const starbucks : CafeName = 'starbucks'
타입스크립트에서 함수를 작성할 때는 function 키워드를 사용하면 된다.
function {함수명}({인자명}:{인자타입}) : {리턴타입}의 형태로 작성하면 된다.
function cafeName(cafe:Cafe) : string {
return cafe.name
}
이번에는 반대로 카페 객체를 반환할 수도 있다.
function cafeMaker(name:string) : Cafe {
return {
name:name
}
}
이때, alias와 인자에 'name'이라고 같은 이름으로 정의되어 있기 때문에 조금 더 짧게 이렇게 쓸 수도 있다.
function cafeMaker(name:string) : Cafe {
return {
name
}
}
이 함수를 화살표 함수로 바꿔보면 이렇게 된다.
const cafeMaker = (name:string) : Cafe => ({name})
아무것도 리턴하지 않는 void 함수를 만들고 싶을 때는 리턴 타입을 명시하지 않으면 된다. 굳이 void를 쓰고 싶다면 리턴 타입에 void를 적어주어도 된다.
function hello() {
console.log('hello')
}
function hello2() : void {
console.log('hello2')
}
never는 자주 보지는 않게 되지만 의미를 알아두면 좋다. 다음과 같은 코드가 있다고 해보자.
function hello(name: string | number) {
if(typeof name === 'string'){
console.log(name)
} else if(typeof name === 'number') {
console.log(name)
} else {
name???????
}
보다시피 name인자는 string 또는 number 타입으로 정해져 있다.
if에서 string 타입이 걸러질 것이고 else if에서는 number타입이 걸러질 것이다.
그러므로 name이 string 또는 number로 정해져 있기 때문에 else에는 어떤 것도 들어갈 일이 없다. 이때 else에 있는 name의 타입을 확인해보면 never로 정의되어 있다.
즉, never는 정상적인 동작에서는 일어날 수 없는 상황을 위한 타입이라고 생각할 수 있다.