TypeScript : Get Start (1)

HaByungNo·2022년 12월 10일
0

Today I Learned

목록 보기
15/16
post-thumbnail

왜 배워야 하는가

단순히 회사에서 이번 플젝때 쓰기로 해서 배운다가 아니라. 왜 타입스크립트여야 하는가에 대한 고찰이 필요하다.

알아갈수록 강력한 타입지정의 힘을 느낄 수 있다. (여기는 아직 정리중...)


types

명시적으로 타입을 선언하는건 최소화 하는게 좋다. 타입스크립트가 알아서 추론하게 하자. 그래야 한줄이라도 코드를 덜 쓴다.

let num : number = 1 // 숫자
let str : string = "hello world" // 문자열
let boo : boolean = true // 불린
let und : undefined = undefined // undefined 
let fnc : function = helloworld() // 함수

let arr : array = [1,2,3,4,5]
// 배열은 왠지 이렇게 하면될거 같지만 이렇게 하면 안됨ㅎㅎ

let arr1 : number[] = [1,2,3,4,5]
let arr2 : string[] = ['hi', 'hello']
let arr3 : boolean[] = [true, false]
// 이렇게 하면 된다.



// type을 any 로 지정하면 그냥 암거나 넣어도 된다.
let anytype : any = [암거나 집어넣어도 됨]
    
  • TypeScript는 any 타입에 대해 엄격하게 검사 또는 체크하지 않는다. 따라서 문제가 없는 코드라고 판단할 수 있지만, 실제로 애플리케이션을 개발하거나 FrontEnd를 개발중 any 타입 때문에 문제가 발생하는 경우가 종종 있다. 따라서 개발자는 항상 any 타입을 조심해서 사용해야 한다.

optional type

let user : {
    name : string
    age? : number  // age 없어도 되는데 
} = {  			   // 만약 있다면 타입은 number 여야 한다.
  name : "daniel"
}

if (user.age > 20) {	// error : 'user.age' is possibly 'undefined'.
    console.log("성인입니다.")
}
// age 는 optional 이기 때문에 undefined 일수도 있어서 에러가 난다.

// 따라서
if (user.age && user.age > 20) {
    console.log("성인입니다.")
}
// 이렇게 바꿔주면 에러가 나지 않는다

Alias

매 값, 객체, 함수 마다 타입을 위처럼 선언하는건 매우 비효율 적인 일이다. 따라서 이렇게 한다.

// 이렇게 Alias 를 선언하여 정해두고
type userType = {
    name : string
    age? : number
}


let user1 : userType = { // : 옆에다 쓴다  
    name : "dan"
}


// 함수 선언시 타입 명시는 아래와 같다.
const userMaker = (name: string) :userType => {
    return {name: name}
}

readonly

Alias 에 아래와 같이 쓴다

type userType = {
    readonly name : string // key 앞에 readonly 추가
    age? : number
}

// 이제 name 의 value 는 수정할 수 없다.
let user1 : userType = {
    name: 'dan',
    age: 30
} 

user1.name = 'IU' // error: Cannot assign to 'name' because it is a read-only property.

배열에도 적용된다.

let arr : readonly number[] = [1,2,3,4,5,6,7]
arr.push(8) // error: Property 'push' does not exist on type 'readonly number[]'.

// 하지만 map, filter array 함수는 사용가능하다
// 배열을 바꾸지 않기 때문이다.

let filterArr = arr.filter((el)=> el>4)
let mapArr = arr.map((el)=>el)
console.log(filterArr) // [5, 6, 7]
console.log(mapArr) // [1, 2, 3, 4, 5, 6, 7] 

Tuple

Tuple 은 배열을 생성하게 한다.
최소한의 길이를 가져야하고 특정 위치에 특정 타입이 있어야 한다.

const user: [string, number, boolean] = [ "daniel", 30, true ]

// 항상 정해진 갯수 정해진 타입의 배열을 지정한다.

unknown, void, never

위에서 정리한 number, string, boolean 등등은 javascript에도 이미 존재했던 익숙한 타입들이다.

추가로 unknown, void, never 3가지 typescript의 special 한 타입들에 대해 알아보자

unknown

// unknown 타입은 any 타입과 동일하게 모든 값을 허용한다. 
let a : unknown; 

// 하지만 할당된 값이 어떤 타입인지 모르기 때문에 
// 함부로 프로퍼티나 연산을 할 수 없다. 
// 따라서 아래와 같이 error 가 난다.
let b = a + 1 // error: 'a' is of type 'unknown'.

// 아래와 같이 타입을 검사한 후 코드를 작성하면 된다.
if (typeof a === 'number') {
    let b = a + 1
}

if (typeof a === 'string') {
a.toUpperCase();
}

void

// 리턴이 없는 함수 = void
const hello = () => {
    console.log('hello')
    return 'hello'
}

const fnc = hello()

fnc.toUpperCase()

never

// never 은 함수가 절대(never) retrun 하지 않을때 발생한다.
// ex : 함수에서 exception(예외)이 발생 했을 때

const hi = ( msg:string | number) => {
    if (typeof(msg) === "string" ){
        msg  // (parameter) msg: string | number
    } else if (typeof(msg) === "number") { 
        msg  // (parameter) msg: number
    } else {
        msg  // (parameter) msg: never
    }
}

call signature

// call signature
// 함수를 선언하고 매개변수 타입을 지정해 봤다
const add = (a:number, b:number) => a+b

// 변수,함수명 에 마우스오버 시 나오는
// "(a: number, b: number) => number" 이런게 call signature 다.
// 어떤 변수를 넣어서 호출해야 하는지 그리고 
// 어떤 타입의 리턴값을 밷는지 알 수 있다.

type Add = (a: number, b: number) => number
const add2 : Add = (a,b) => a+b
// 함수를 구현하기 전에
// 개발자가 미리 타입을 정의하고, 
// 이 함수가 어떻게 작동하는지 서술해둘 수 있다.
 

overloading

function overloading, method overloading 이라고도 한다.

우리가 써왔고 앞으로 쓸 대부분의 라이브러리에서 오버로딩을 엄청 많이 사용한다.

// 위에서 본 call signature 를 이렇게 정의 할 수도 있다.
type Add = {
    (a: number, b: number) : number
}

// 오버로딩은 함수가 '서로 다른 여러개' 의 call signature 를 가지고 있을 때 발생된다.

type Add2 = {
    (a: number, b: number) : number
    (a: number, b: string) : number
}

                    // (parameter) b: string | number
const add2 : Add2 = (a,b) => a+b 
// error : Operator '+' cannot be applied to types 'number' and 'string | number'.

// 이렇게 조건을 걸어야 한다. 
const add: Add2 = (a,b) => {
    if (typeof b === 'string') return a
    return a+b
} 

// 간단하게 생각하면 오버로딩은 여러 call signature 가 있는 함수일 뿐이다.

NextJS 에서 다시한번 오버로딩을 정리할 기회가 있을듯?

profile
프라고

0개의 댓글