Typescript

[Typescript] 기본 타입 알아보기

__ellie 2021. 6. 17. 00:26
반응형

타입스크립트 기본 타입

이번 글에서는 타입스크립트 기본 타입을 정리했습니다.

Array vs string

  • 이 둘의 차이점은 readonly 변수를 만들 때 차이가 난다.
  function pushNumber(numbers: readonly number[]) {
      numbers.push(1) // warning (x)
  }

  function pushNumber(numbers: readonly Array<number>) {
      numbers.push(1) // 'readonly' type modifier is only permitted on array and tuple literal types
  }
  • Object의 불변성을 보장하기 하고 일관성 있는 코드를 작성하고 싶다면 string[]을 사용하는 것이 좋다.
  • Tuple은 언제 사용할까?
  • Tuple은 서로 다른 타입을 가질 수 있는 배열이다. 지금까지 Tuple을 사용한 적이 거의 없었는데 Tuple은 언제 사용할까?
  • => tuple 사용을 권장하지 않는다!
  • 데이터에 접근할 때 정의를 찾아보지 않는 이상 어떤 데이터가 있는지 모른다.
  let person: [string, number]

  person = ['ellie', 40]

  [name, age] = person;
  • 이런식으로 사용할 수 있다. 이렇게 사용하면, 데이터를 정하는 곳이 아니라 데이터를 사용하는 곳에서 이름을 결정해야 하기 때문에,
    어떤 식으로 구현이 되어 있는지 알아야 한다.
  • 리액트의 경우,
  [name, setName] = useState('ellie')
  • 이런 식으로 리턴 타입을 튜플을 사용해서 정의했는데, 이런 경우에는 사용자가 다양한 타입의 초기값과 이름을 정할 수 있고 업데이트할 수 있다는 점에서 튜플을 유연하게 사용했다고 볼 수 있다.
  • 하지만 interface, type alias, class로 사용할 수 있다면 tuple은 가급적 사용하지 않는 것이 좋다.

Union 타입

  • 발생할 수 있는 케이스 중 하나만 사용할 때
  type SuccessState = {
      response: {
          body: string; 
      }
  }

  type FailsState = {
      reason: string; 
  }

  type LoginState = SuccessState | FailState; 

  function login(id: string, password: string): Promise<LoginState> {
      return {
          response: {
              body: 'logged in'
          }
      }
  }

  function printLoginState(state: LoginState) {
      if(state typeof SuccessState) {
          console.log(`good! ${state.response.bdoy}`)
      }
      console.log(`sorry! ${state.reason}`)
  }
  • 코드를 작성하는 시점에는 어떤 state가 들어올지 모르기 때문에
  • 어떤 타입인지 조건문을 달아야 하는데, 보통 위와 같이 쓴다.
  •  if('response' in state)
  • { // 로그인 성공 }else { // 로그인 실패 }

위와 같이 typeof 키워드 대신에 in 키워드를 사용할 수 있지만 비추!

Discrimintated Union

  • 위와 같은 상황에서 사용할 수 있는 것이 Discriminated Union 타입인데,
  • 유니온 타입에 차별화되는 이름이 동일한 타입을 둠으로써 간편하게 구분할 수 있는 것을 말한다.
  • 직관적으로 코드를 작성할 수 있고, 읽을 때도 직관적으로 읽을 수 있다.
  • 공통적인 프로퍼티를 가지고 있음으로써 구분하기 쉽게 만든다.
  type SuccessState = {
      result: 'success', 
      response: {
          body: string, 
      }
  }

  type FailState = {
      result: 'fail', 
      reason: string, 
  }

  type LoginState = SuccessState | FailState; 

  function printLoginState(state: LoginState) {
      if(state.result === 'success') {
          console.log('성공!')
      }
  }

Intersection 타입

  • and의 개념
  type person = {
      name: string; 
      score: number; 
  }

  type Worker = {
      employeeId: number; 
      work: () => void; 
  }

  function internWork(person: Student & Worker) {
      console.log(person.name, person.employeeId, person.work()) 
  }

  internWork({
      name: 'ellie', 
      score: 1, 
      employeeId: 1, 
      work: () => {}
  })

Enum

  • enum은 여러가지의 관련된 상수 값들을 한 곳에 모아서 정의할 수 있도록 한 것
  • 자바스크립트에서는 enum타입이 존재하지 않는다.
  • 관련있는 상수값을 모아서 관리할 수 있다.

Enum을 사용하면 안되는 이유?

  • 다른 언어에서 enum이 유용하다.
  • 하지만, 타입스크립트에서 enum은 가능한 사용하지 않는 것이 좋다.
enum Days = {
    Monday, 
    Tuesday
}

let day: Days = Days.Monday; 
day = 1; 
day = 10; // 컴파일 에러가 발생하지 않는다.
  • 타입스크립트 컴파일을 돌리면 에러가 발생하지 않는다.
  type DaysOfWeek = 'Monday' | 'Tuesday' | 'Wednesday' 

  let dayOfWeek: DaysOfWeek = ''; 
  dayOfWeek = 'ellie' (x)
  • enum은 union string literal로 대체되어 사용할 수 있다.
  • enum은 대부분 케이스에서 union으로 대체하여 사용할 수 있다.
  • union으로 대체하여 타입을 보장하면서 사용할 수 있다.

타입추론? 언제 쓸까?

  • 타입을 명확하게 명시해야 하는 경우보다 알아서 타입이 결정되는 경우가 있다.
  • 타입이 뻔한 경우에는 생략해서 작성하는 것도 괜찮다
  • 딱 봐도 타입을 알 수 있다면 적지 않아도 되지만, 프로젝트에서는 복잡한 함수가 많기 때문에 명확하게 해주는 것이 좋다.

type assertion

  • 타입을 확인할 때 타입을 강요할 때가 있는데 이럴 때 type assertion을 써야 하는데
  • type assertion에 관련된 것을 많이 사용하고 있다면 쓰지 않으려고 고민해 보는 것이 좋다.
  • 하지만 타입스크립트는 타입이 없는 자바스크립트와 함께 연동되는 경우가 있기 떄문에 불가피하게 써야 하는 경우가 생긴다.
  function jsStrFunc(): any {
      return 10; 
  }

  const result = jsStrFunc();
  result.length // 하지만 result가 any 타입이기 때문에...

  (result as string).length; 
  • 이런 경우 type assertion을 사용해야 한다.
  • 확신할 수 있을 때만 type assertion을 사용하자!
  • 확신을 해서 썼지만, 실제로 함수에서 숫자를 리턴한다면, 작성 시점에는 타입스크립트에서 에러가 발생하지 않는다.
  • 실행하는 순간 undefined라고 나온다.
  • 애플리케이션이 죽거나 예외가 발생하지 않지만, 예상치못한 결과가 나올 수 있다.
  • const wrong: any = 5; console.log(wrong as Array<number>.pus(1)); // err wrong.push is not a function

```

  • 위의 예시에서는 에러가 발생하고 애플리케이션이 종료된다.
  • 정말 정말 장담할 수 있을 때만 쓰도록 하자!