자바스크립트는 매우 유연한 언어이다. 개발자가 잘못 코드를 작성하였다고 하더라고 이해하려 도와주려고 한다.
[1, 2, 3, 4] + false // "1, 2, 3, 4false"
숫자로 이루어진 배열에 boolean값을 합치면 위와 같은 현상이 일어나게 된다.
위와 같이 되었을 때 문제점이 무엇일까?
첫 번째로 원하지 않게 배열이 완전히 사라지게 된다.
두 번째로 boolean인 false는 그냥 string의 형태로 바뀌어 버린다.
⇒ 이런 문제는 엄청 이상한 일인데 Js는 이를 허용해주고 있다는 것이다.
다른 예제를 살펴보자.
function divide(a,b){
return a/b
}
divide(2,4) // 0.5
divide("xxx") // NaN
Js는 현재 이 함수를 올바르게 사용하도록 강제하고 있지 않는다는 점이 있다. divide("xxx")를 입력했을 때 결과값으로 NaN이 나오게 된다는건 Js가 코드 실행을 막아주고 있지 않고 있다는걸 말한다.
입력값 두개를 보내야 실행되는 함수를 만들었는데 Js는 아무 에러값 없이 실행시키고 만것이다.
⇒ Js는 a와 b가 필수 입력값인지 선택사항인지 전혀 알고 있지 못한다. 위의 설정에서도 사용자가 컴퓨터에게 a와 b의 값이 숫자로만 들어가야한다고 알려주지 않고 있다.
최악의 에러는 런타임 에러이다.
const nico = {name : "nico"}
nico.hello() // 타입에러 발생
위에서 발생하는 Uncaught TypeError는 유저의 컴퓨터에서 코드가 실행되면 나타나는 에러이다. 위의 Hello()함수를 nico라는 객체안에서 분석해서 해당함수가 없다는걸 알려줬다면 실행 이전에 런타임에러를 방지해줄 수 있었을 것이다.
개발자가 원하는건 이러한 상황이 일어나지 않게 에러를 반환하여 일깨워 주는 것이다.
위와 같은 이유로 TypeScript를 사용하는 이유를 알아보았다. 그럼 이제, TypeScript가 무엇인지 알아보자. TypeScript는 프로그램 언어이다. 브라우저는 TypeScript가 아닌 Js를 인식하기 때문에 TypeScript는 브라우저가 이해할 수 있도록 먼저 Js로 변환되어야 한다.
즉, Js가 컴파일 되기전 TypeScript로 쓰여진 코드가 Js로 변환될 때, 정상적으로 바뀌게 된다면 위와 같은 문제가 발생하지 않는다는 것이고 TypeScript가 Js로 변환될 때 문제가 생긴다면 위와 같은 문제가 생길 수 있을음 암시해준다.
const player = {
name : "nico"
}
위와 같은 객체가 선언이 되어있다고 할 때, age를 추가하려고 한다. age는 있어도 되고 없어도 되는 값인데 어떻게 TypeScript로 선언해줄 수 있을까?
const player : {
name : string,
age? : number
} = {
name:"nico"
}
age가 있을지 없을지 모르는 상황인 optional type일 경우에는 "?"를 사용하여 정의해 줄 수 있다. age를 보면 number | undefined로 설정이 되어있게 된다. 하여 조건문인 if를 사용할 때 조심해줘야 하는 부분이 있다.
if(player.age <10)
위와 같이 사용하면 TypeScript가 오류를 알려주게 된다. age가 undefined일 경우도 있기 때문이다. 하여 위와 같은 에러를 없애려면 아래와 같은 코드로 바꿔주어야한다.
if(player.age && player.age < 10)
const player : {
name : string,
age? : number
} = {
name:"nico"
}
const footBallplayer : {
name : string,
age? : number
} = {
name : "Lynn",
age : 12
}
위의 코드를 보면, 중복되는 코드가 보인다. (name과 age가 중복으로 겹침) 선언이 완전 같을 때, type Alias(타입 별칭)으로 더 적은 코드를 사용할 수 있게 해준다.
type Player = {
name : string,
age? : number
}
const player : Player = {
name:"nico"
}
const footBallplayer : Player = {
name : "Lynn",
age : 12
}
맨 위에 type을 정해주고 선언을 해주면 같은 타입을 정의해 줄 수 있다. type을 선언할 경우 첫 글자는 대문자로 선언을 해야한다.
함수가 리턴하는 값의 type을 알 수 있으면 보호장치를 만들어 줄 수 있다.
function playerMaker (name : string){
reutrn {
name : name
}
}
const nico = playerMaker("nico")
nico.age = 12 // 에러 발생
Js에서는 위와 같은 선언으로 반환된 객체에 age라는 키와 12라는 값을 추가해 줄 수 있었다. TypeScript에서는 위와 같은 상황을 인지할 수 없기 때문에 type을 Alias로 선언해 주었던것 처럼 선언해주어야한다.
type Player = {
name : string
age? : number
}
function playerMaker (name : string){
reutrn {
name : name
}
}
const nico = playerMaker("nico")
nico.age = 12 // 에러 발생
화살표함수의 경우 아래와 같이 선언하면 되겠다.
type Player = {
name : string,
age? : number
}
const PlayerMaker = (name : string) : Player => {return{name : name}} // === ({name : name})
const nico = playerMaker("nico")
nico.age = 12
readonly의 선언이 되어 있다면 수정이 불가능하게 할 수 있다.
=> 불변성을 가질 수 있게 해준다.
type Player = {
readonly name : string
age? : number
}
const PlayerMaker = (name : string) : Player => ({name : name})
const nico = playerMaker("nico")
nico.age = 12
nico.name = "las" // 에러 발생
Tuple은 배열을 생성할 수 있게 해주는데 최소한의 길이를 가져야 하고 특정 위치에 특정 타입이 선언되어야 한다.
const player = ["nico", 12, false]
위와 같이 배열이 하나만의 type만 들어가는게 아니라, 여려 type이 들어갈 경우에 사용되게 된다.
const player : [string, number, boolean] = ["nico", 12, false]
위와 같이 자리에 어떤 type이 들어갈지 하나하나 정해줄 수 있다. 위오 ㅏ같이 선언해주는 것을 tuple이라고 한다. 마찬가지로 readonly와 같이 사용할 수도 있다.
const player : readonly [string, number, boolean] = ["nico", 12, false]
player[0] = "hi" // 에러 발생
TypeScript로 부터 빠져나오고 싶을 때 사용하는 타입이다. Js에서 사용했을 때 처럼 그대로 적용 될 수 있도록 사용할 수 있다. any는 어떤 type이든 될 수 있기 때문이다.
const a : any[] =[1,2,3,4]
const b : any = true
console.log(a + b) // '1,2,3,4true'
변수의 타입을 미리 알지 못 할 때 사용한다.
let a : unknown
let b = a + 1 // 에러 발생
a의 type이 unknown이기 때문에 (number가 아니기 때문에) type에러가 나게 된다.
let a : unknown
if(typeof a === "number"){
let b = a + 1
}
하지만 위와 같은 경우처럼 if의 범위 안에서는 a가 number가 될 수 있기 때문에 위와 같은 문법이 허용될 수 있다.
아무것도 return 하지 않는 함수를 대상으로 사용한다. return 하지 않는 함수에 void를 따로 지정해주지 않아도 된다.
function hello(){ // function hello() : void
console.log('x')
}
return 되는 값이 없는 함수에 마우스 포인터를 가져다 대면 위의 주석처럼 void에 관한 안내문이 나오게 된다.
⇒ TypeScript는 이 함수가 아무것도 return하지 않는다는 것을 자동으로 인식하게 된다.
함수가 절대 return하지 않을 때 발생하게 된다.
⇒ 함수에서 예외가 발생할 때 사용.
function hello() : never {
return "x" // 오류 발생
throw new Error("xxx") // 실행
}
return하지 않고 오류를 발생시키는 함수
function hello (name : string|number){
if(typeof name === "string"){
name // name : string
} else if(typeof name === "number"){
name // name : number
} else {
name // name : never
}
}
위와 같은 코드가 있다면 name에는 문자나 숫자의 경우가 올 수 있게 된다. 만약 파라미터가 제대로 들어오게 된다면 else에 있는 코드는 작동되지 않을 것이다.