8주차
1. Introduction
1.5 Why not JavaScript
Why TypeScript? : Type Safety
타입 안정성 - 코드에 버그 감소, 런타임 에러 감소, 더 나은 개발자 경험과 생산성
자바스크립트
- 매우 유연한 언어. 에러를 보여주지 않으려고 노력함
[1, 2, 3, 4] + false -> '1,2,3,4false' 와 같이 이상한 코드를 써도 에러가 나지 않음
2. Overview of Typescript
2.0 How Typescript Works
Typescript : a strongly typed programming language that builds on Javascript.
브라우저는 자바스크립트를 이해하므로 타입스크립트는 자바스크립트로 컴파일된다.
TS는 변환 전 먼저 코드를 확인하여, 에러가 발생할 것 같은 코드를 감지하면 컴파일하지 않음으로써 변환된 js 안에서 오류가 발생하지 않도록 돕는다.
-> 이러한 보호장치는 컴파일 전에 실행되므로 런타임 오류가 발생하지 않도록 한다.
2.1 Implicit Types vs Explicit Types
타입 추론
let a = "hello" //a는 string type
a = "bye"
a = 1 //오류
직접 타입 명시
let b : boolean = true
let c : number[] = []
2.2 Types of TS part One
const player : {
name: string,
age?: number
} = {
name: "cado",
}
player : object 타입
name : string 타입
age: number 타입 or undefined
type Player = { // Type Alias
name: string,
age?: number
}
const cado : Player = {
name: "cado",
}
const nana : Player = {
name: "nana",
age: 4
}
type Player = { // Type Alias
name: string,
age?: number
}
function playerMaker(name: string) : Player {
return {
name //name: name
}
}
const cado = playerMaker("cado")
cado.age = 6 //ts가 cado가 Player 타입인 것을 알고 있기에 오류 X
const playerMaker = (name: string) : Player => ({name})
const cado = playerMaker("cado")
cado.age = 6 //ts가 cado가 Player 타입인 것을 알고 있기에 오류 X
2.3 Types of TS part Two
readonly property
type Player = { // Type Alias
readonly name: string,
age?: number
}
const playerMaker = (name: string) : Player => ({name})
const cado = playerMaker("cado")
cado.name = "babo" //name은 readonly이기에 수정 불가
const numbers: readonly number[] = [1,2,3,4]
numbers.push(1) //readonly이기에 push를 허용핮 ㅣ않음
Tuple
array를 생성함. 단 최소한의 길이를 가져야 하고 특정 위치에 특정 타입이 존재해야 함
const player: [string, number, boolean] = ["cado", 1, true]
player[0] = 1 //1번째 요소는 string이어야 하므로 오류
any
타입에 의한 오류들을 없애기 위해 (js처럼 작동) 사용. typescript의 보호장치를 비활성화시킴
2.4 Types of TS part Three
unknown
변수의 타입을 당장 알 수 없을 때 사용
let a : unknown;
//사용 시 타입 체크 필요
if (typeof a === 'number'){
let b = a + 1
}
void
아무것도 리턴하지 않는 함수 대상으로 사용
never
함수가 절대 리턴하지 않을 때 사용
function hello() : never {
throw new Error("xxx")
}
function hello(name: string | number) {
if(typeof name === "string"){
//이때 name은 string
} else if (typeof name === "number"){
//이때 name은 number
} else {
//이때 name은 never (name을 string or number 타입으로 지정했기에
//타입이 맞게 들어온다면 실행되지 않음)
}
}
3. Functions
3.0 Call Signatures
함수의 argument 타입, 반환 타입을 알려주는 부분
type Add = (a: number, b:number) => number; //함수의 call signature 타입 만들기
const add:Add = (a,b) => a+b;
3.1 Overloading
함수가 서로 다른 여러 개의 call signatures를 가지고 있을 때 발생
type Add = {
(a: number, b: number) : number
(a: number, b: string) : number
}
const add : Add = (a,b) => a+b //b는 string or number이기 때문에 a+b는 오류
const add2:Add = (a,b) => {
if (typeof b === "string") return a
return a+b
}
type Add = {
(a: number, b: number) : number
(a: number, b: number, c: number) : number
}
//call signature에서 파라미터의 개수가 다른 경우
const add:Add = (a,b,c?:number) => {
if(c) return a+b+c
return a+b
}
3.2 Polymorphism(다형성)
제네릭
타입 부분에 placeholder을 적어 사용 시 작성한 코드의 타입으로 대체
type SuperPrint = {
<T>(arr: T[]) : T //call signature이 제네릭을 사용함을 명시
}
const superPrint : SuperPrint = (arr) => arr[0]
const a = superPrint([1,2,3,4]) //number
const b = superPrint(["a","b"]) //string
const c = superPrint([1,2,true,false]) //number | boolean
TS가 알아낸 타입으로 콜시그니처의 T 타입을 바꿔줌
TS는 제네릭이 처음 사용되는 지점을 기반으로 타입을 알게 됨
type SuperPrint = {
<T, M>(a: T[], b: M): void
}
const superPrint : SuperPrint = (a, b) => {
console.log(a[0], b)
}
const a = superPrint([1,2,3,4], "X")
제네릭도 여러 개 사용 가능
type Player<E> = {
name: string
extraInfo: E
}
type CadoExtra = {
favFood: string
}
type CadoPlayer = Player<CadoExtra>
const cado: CadoPlayer = {
name: 'cado',
extraInfo: {
favFood : "밥"
}
}
const nana: Player<null> = {
name: 'nana',
extraInfo: null
}