Web Dev/ELICE

21 (1/2) :: 타입스크립트, Type, Utility Types

HJPlumtree 2021. 11. 23. 14:41

엘리스 SW 엔지니어 트랙 21일차

박성국님 실시간 강의날

 

 

노드와 타입스크립트를 강의해주실 박성국님

 

프로그래머가 되면

코드를 쓰는 시간보다 코드를 읽는 시간이 늘어난다 하신다

 

 

 

타입스크립트(TypeScript)

트랜스파일러다 Babel과 같은 

 

JavaScript의 슈퍼셋이라 말한다

JavaScript의 모든 기능과 + 추가적인 기능도 제공

 

Type(유형) => 명시적인 데이터를 설명

컴파일 언어

 

TypeScript를 왜 사용하나?

규모가 크면 TypeScript를 사용하는 것 같다고 하신다

코드를 읽을 기회가 많아지는데,

보고 이해하기 좋은 코드(클린코드)를 사용하는데 도움이 된다

 

 

객체 복사

헷깔릴 수 있는 객체 복사 참고용

box1 = Object.assign({}, box)
box2 = {...box, borderRadius: 10}
box3 = JSON.parse(JSON.stringify(box))

// JSON.parse() 오브젝트화 시키는것

 

 

TypeScript에 추가된 기본 Type

 

Tuple

let x: [string, number]

x = ['a', 3]

x = ['hello']

x = ['hello', '40']

x.push(42) // 이러면 오류가 안나...

 

 

enum

// 1
enum Color {Red, Green, Blue} // 0, 1, 2 값 할당된다

/*
[LOG]: {
  "0": "Red",
  "1": "Green",
  "2": "Blue",
  "Red": 0,
  "Gree": 1,
  "Blue": 2
} 
*/

// 2
enum Color {Red = 1, Green, Blue} // 1, 2, 3 값 할당된다

/*
[LOG]: {
  "1": "Red",
  "2": "Green",
  "3": "Blue",
  "Red": 1,
  "Green": 2,
  "Blue": 3
} 
*/

// 3
enum Color {Red = 1, Green = 4, Blue =6 } // 1, 4, 6 값 할당된다


/*
[LOG]: {
  "1": "Red",
  "4": "Green",
  "6": "Blue",
  "Red": 1,
  "Green": 4,
  "Blue": 6
} 
*/

 

 

any

그냥 자바스크립트와 같은 변수지정이라

사용할 필요가 없어보인다

let notSure: any = '4'

 

 

함수 return 타입 지정

// return이 없는 경우 void
function warnUser(): void {
    console.log('This is my warning message')
}

// return이 있는 경우
function tremp(age: number): number {
    return age
}

 

 

null, nudefined

null 혹은 undefined만 받을 수 있다

let u: undefined = undefined
let n: null = null

 

 

never

절때 반환하지 않을 때 사용

function error(message: string): never {
    throw new Error(message)
}

function infiniteLoop(): never {
    while(true) {
        
    }
}

 

 

타입별칭(커스텀 타입)

//일반타입
let x: number = 10
let xPosition: number = 10

//타입별칭
// type YesOrNo = string
type YesOrNo = 'Y' | 'N'

let answer: YesOrNo = 'Y'
// let answer: YesOrNo = 'U' // 에러

/*** 함수에도 사용 가능 ***/
// 인지가 없고, return 값이 string인 함수
type FooFunction = () => string

// 이렇게만 사용 가능
let temp: FooFunction = () => {
    return 'temp'
}

// 이러면 오류
/*
let temp: FooFunction = ('age') => {
    return 'temp'
}
*/

 

 

interface

객체 정의할 때 interface 사용한다

 

type Name = string

interface IUser {
    id: number
    name: Name
    email: string
}

// 위 interface 문법과 같은 행동을 한다
/*
type TUser = {
    id: number
    name: Name
    email: string
}
*/

// 이러면 interface에 합쳐진다
interface IUser { address: string}

// 하지만 type은 오류
/*
type TUser { address: string }
*/

let my: IUser = {
    id: 3,
    name: 'HJ',
    email: 'yohoho@example.com',
    address: 'North pole'
}

 

 

인터페이스에 대한 김병철 코치님의 설명

인터페이스의 경우, 컴파일하는 과정에서 전부 합쳐지고 -> 해당 인터페이스에 대응하는 객체를 생성해주는 과정을 거칩니다. (JS의 호이스팅을 떠올릴 수 있지만, 실제 동작과정은 약간 다릅니다. 사실 일반적으로 인터페이스, 클래스 등의 정의는 최상단에 고정하고 추가적으로 수정하는 것은 지양하는 편 입니다.)

 

 

Utility Types

keyof

interface User {
    id: number
    name: string
    age: number
    gender: 'm' | 'f'
}

type UserKey = keyof User
// 'id' 'name' 'age' 'gender'

 

 

Partial<T>

// Partial<T>

interface User {
    id: number
    name: string
    age: number
    gender: 'm' | 'f'
}

//  원래 이렇게 다 필수 항목
/*
let admin: User = {
    id: 2,
    name: 'dear',
    age: 11,
    gender: 'f'
}
*/

// 하지만 Partial 사용하면 선택사항
let admin: Partial<User> = {
    id: 2,
    name: 'dear'
}

// 이렇게 interface 자체에 사용 가능
interface User {
    id: number
    name: string
    age: number
    gender?: 'm' | 'f'
}

 

 

Required<T>

써도 되고 안써도 되게 Partial에서 설정해도

이 녀석을 거치면 필수가 된다

// Required<T>

interface User {
    id: number
    name?: string
}

let admin: Required<User> = {
    id: 1,
    name: 'John'
}

 

 

Readonly <T>

// Readonly<T>

interface User {
    id: number
    name: string
    age: number
    gender: 'm' | 'f'
}

// 읽기전용으로 만들어 주는 Readonly
let admin: Readonly <User> = {
    id: 2,
    name: 'dear',
    age: 11,
    gender: 'f'
}

// 이렇게 하면 오류
admin.id = 3

// 혹은 interface에서 만들 수 있다

interface User {
    id: number
    name: string
    age: number
    readonly ender: 'm' | 'f'
}

 

 

Record <K, T>

Record<속성값, 타입>

// Record <K, T>

type Grade = '1' | '2' | '3' | '4'
type Score = 'A' | 'B' | 'C' | 'D'

const score: Record<Grade, Score> = {
    1: 'A',
    2: 'B',
    3: 'C',
    4: 'E' // error
}
interface User {
    id: number
    name: string
    age: number
}

function isValid(user: User) {
    const result: Record<keyof User,boolean> = {
        id: user.id > 0,
        name: user.name !== '',
        age: user.age > 0
    }
    return result
}

 

 

Pick<T,K>

속성값(키)를 선택하는 것

// Pick<T,K>
interface User {
    id: number
    name: string
    age: number
    gender: 'm' | 'f'
}

const admin: Pick<User, 'id'|'name'> = {
    id: 0,
    name: 'John'
}

 

 

Omit<T, K>

속성값(키)를 선택해서 제외 하는 것

// Omit<T,K>
interface User {
    id: number
    name: string
    age: number
    gender: 'm' | 'f'
}

const admin: Omit<User, 'id'|'name'> = {
    age: 0,
    gender: 'm'
}

 

 

Exclude<T1, U>

타입 제외

// Exclude<T1,K>

type T1 = string | number | boolean
type T2 = Exclude<T1, number | string>

let isNum: T2 = true
let isNum: T2 = 3 // error

 

 

NonNullable<T>

null과 undefined를 제외

// NonNullable<T>

type T1 = string | null | undefined | void
type T2 = NonNullable<T1>

let proudct: T2 = 'asdf'
let empty: T2 = null // error

 

 

Parameters<T>

함수로 지정해놓은 타입을 인자로 받고,

인자를 튜플로 반환

 

// Parameters<T>

type T0 = Parameters<() => string> // 빈배열 [] 반환
type T1 = Parameters<(s: string) => void> // [string]

let T1Arr: T1 = ['Yohoho'] 
console.log(T1Arr) // ["Yohoho"]

 

 

ReturnType<T>

얘도 함수 들어간다

 

// ReturnType<T>

type T0 = ReturnType<() => string> 

let str: T0 = 's'

console.log(str) // "s"

 

 

21 (2/2) :: TypeScript 함수 사용, class

링크 => https://forgottenknowledge.tistory.com/entry/21-22-TypeScript-%ED%95%A8%EC%88%98-%EC%82%AC%EC%9A%A9-class

 

 

types of Deon Black #unsplash