TypeScript 기초 문법 - 1

이현우·2023년 4월 3일
0

TypeScript 완전정복

목록 보기
2/2
post-thumbnail

타입스크립트의 기본 Usage

타입스크립트는 자바스크립트에 변수, 매개변수, 리턴값에 타입 붙여놓는 것 정도로 생각하면 편함

const a: number = 5;
const b: string = '5'
const c: boolean = true
const d: undefined = undefined
const e: null = null
const f: symbol = Symbol.for('f')
const g: bigint = 1000000n
const h: any = any // typescript가 아닌 javascript를 사용하는 격

// 리터럴 타입 (type은 보다 정확하게)
const i: 5 = 5;
const j: true = true;

// 패러미터, 리턴값에 타입 붙이기
function add(x: number, y: number): number { return x + y }
const add: (x: number, y: number) => number = (x, y) => x + y;
const obj: { lat: number, lon: number } = { lat: 37.5, lon: 127.5 };

// 배열
const arr: number[] = [123, 456]
// 아래와 같은 방식으로도 사용 가능
// const arr: Array<number> = [123, 456]

// tuple
const arr2: [number, number, string] = [123, 456, 'abc']

Type Alias

type으로 타입을 선언하는 방식

type Add = (x: number, y: number) => number

interface

interface로도 타입 선언이 가능

interface Add {
  (x: number, y: number): number
}

타입 추론

위의 코드에서 타입을 지워도 에디터 자체에서 타입을 제대로 처리하고 있다면 그냥 에디터에서 결정한 타입 사용하는게 좋음

타입이 있는 곳에서 타입을 생략하는 쪽으로 코드 작성해보기

Case

const a: string = '5'
// 튜플로 사용하려고 했는데 음...
const arr = [123, 456, 'avc']
// 이런 경우에 타이핑
const arr: [number, number, string] = [123, 456, 'avc']

'5'로 type narrowing을 할 수 있는데 이걸 string으로 타입을 넓힘 (부정확한 타입 사용)

Javascript 변환

정의된 타입과 ts 파일에서 사용된 타입들을 삭제한다

Case

// 정의부와 구현부를 따로 둔다
// 정의부는 js에서 삭제
function add(x: number, y: number): number
function add(x, y) { return x + y }

// as문도 삭제
let aa = 123
aa = 'hello' as unknown as number // 강제 형변환

never와 not-null assertion

빈 배열과 never

빈 배열은 never로 처리하기 때문에 typing을 반드시 해줘야됨

try {
  const array: string[] = []
  array.push('hello')
} catch(error) {
  error
}

! 대신 if

const head = document.querySelector('#head')!; // Element | null인데...?
// null 절대 아님, 진짜로(not-null assertion) => !
console.log(head);

// 제발 안전하게 사용해 (if 사용하기)
const head = document.querySelector('#head');
if (head) {
  console.log(head);
}

Primitive Wrapper, Template Literal, rest

Primitive Wrapper

// 객체 래퍼 타입은 웬만하면 쓰지마
const hell: String = 'hell'
const whenToUse = new String('in here')

Template Literal

type World = 'world' | 'hell'
const a: World = 'world'

type Greeting = `hello ${World}`
const b: Greeting = 'hello world' // 이렇게 추천받을 수 있음

rest

function rest(...args: string[]) {
  console.log(args) // [1, 2, 3]
}

rest('1', '2', '3');

tuple의 위험한 점: Array.push는 사용하면 좀 힘들어짐

const tuple: [string, number] = ['2', 3]

// 얜 막아줌
tuple[2] = 4

// 근데 이건 못 막아줌
tuple.push(4)

enum과 custom typing

enum

// 값도 지정 가능
// js에서 사라지는 코드
const enum EDirection {
  Up, Down, Left, Right
}

// 이 정의는 남아있음
// 웬만하면 남기는게 좋을 수 있음
// as const를 지우면 readonly + number로 typing 됨
const ODirection = {
  Up: 0,
  Down: 1,
  Left: 2,
  Right: 3
} as const

const a = EDirection.Up

실제 사용처

// enum
function walk(dir: EDirection) {}

// as const
// keyof는 객체의 key를 가져오기
// 아래의 정의는 value들만 typing하기
type Direction = typeof ODirection[keyof typeof ODirection]
function run(dir: Direction) {}

keyof: 타입의 key를 빼오기

const obj = { a: 1, b: 2, c: 3 }
// typeof obj => { a: number, b: number, c: number }
// keyof typeof obj => "a" | "b" | "c"
type Key = keyof typeof obj

union과 intersection

  • 간단하게 타입을 만들고 싶으면 type, 객체지향적인 부분을 섞어서 사용하고 싶다면 interface 사용

Union (|)

type A = string | number
// 둘 다 가능
const a: A = 2
const b: A = '2'

문제점...

function add(x: string | number, y: string | number): string | number { return x + y }

위 함수는 리턴값에 대한 타이핑이 오류라고 나옴

const result = add(1, 2)

result는 number인데 string으로도 착각할 수 있는 문제가 발생함 이러면

result.charAt(2)

이런 경우에 제대로 동작이 안되는 경우가 있음

intersection (&): 타입은 모든 조건을 만족해야한다

type A = string & number
const a: A = 1; // 되겠냐

// 객체는 아래 prop을 모두 가져야 한다
// union은 아래 속성 중 하나만 가지고 있으면 된다
type A = { hello: 'world' } & { zero: 'cho' }
const a: A = { hello: 'world',  }

Type Alias, Inheritance(Interface)

type Animal = { breathe: true }
type Human = Animal & { think: true }

// 둘 다 있어야 한다고
const nunu: Human = { breathe: true, think: true }

위의 방식말고도 기존 타입을 확장시키는 방식이 더 있음

interface Animal {
  breathe: true
}
interface Human extends Animal {
  think: true
}

interface의 특성: 중복선언이 가능하고 이는 겹쳐진다

interface A {
  talk: () => void
}
interface A {
  eat: () => void
}
interface A {
  shit: () => void
}

const a: A = { talk() {}, eat() {}, shit() {} }
profile
이현우의 개발 브이로그

0개의 댓글