모던 리액트 Deep Dive 스터디

선택이 아닌 필수, 타입스크립트

려낭 2024. 11. 7. 22:11

1.7.1 타입스크립트란?

 

타입스크립트

 

ㄴ기존 자바스크립트 문법에 타입을 가미한 것.

 

자바스크립트는 기본적으로 동적 타입의 언어이기때문에 대부분의 에러를 코드를 실행했을 때만 확인할 수 있다는 문제점이 있다.

 

typeof를 적용하여 문제점을 방지할 수 있지만 너무 번거롭고 코드의 크기를 과도하게 키우게 된다.

 

타입스크립트는 이러한 자바스크립트의 한계를 벗어나 타입 체크를 정적으로 런타임이 아닌 빌드 타임에 수행할 수 있게 해준다.

 

 

 

1.7.2 리액트 코드를 효과적으로 작성하기 위한 타입스크립트 활용법

 

any 대신 unknown을 사용하자

 

any는 불가피할 때만 사용해야하는 타입.

 

타입을 any로 설정하면 타입스크립트가 에러를 발생시키지 않는다고 하더라도 실행 시 에러가 발생할 것이다.

이는 타입스크립트를 사용하는 이점을 모두 없애버린다.

 

불가피하게 아직 타입을 단정할 수 없는 경우에는 unknown을 사용하자!

unknown은 어떠한 값도 할당할 수 있지만 any와는 다르게 이 값을 바로 사용하는 것은 불가능하다.

 

unknwon은 예상치 못한 타입을 받아들일 수 있음은 물론, 사용하는 쪽에서도 안전하게 쓸 수 있다.

 

 

타입 가드를 적극 활용하자

 

타입을 사용하는 쪽에서는 최대한 타입을 좁히는 것이 좋다.

타입을 좁히는 데 도움을 주는 것이 바로 타입 가드다.

조건문과 함께 타입 가드를 사용하면 타입을 효과적으로 좁힐 수 있어 더 명확하게 변수나 함수를 사용할 수 있다.

 

instanceof : 지정한 인스턴스가 특정 클래스의 인스턴스인지 확인할 수 있는 연산자.

typeof : 특정 요소에 대해 자료형을 확인하는데 사용하는 연산자.

in : property in object로 사용되며, 주로 어떤 객체에 키가 존재하는지 확인하는 용도로 사용된다.

 

제네릭

  • 함수나 클래스 내부에서 단일 타입이 아닌 다양한 타입에 대응할 수 있도록 도와주는 도구.
  • 타입만 다른 비슷한 작업을 하는 컴포넌트를 단일 제네릭 컴포넌트로 선언해 간결하게 작성할 수 있다.
  • > 사용할 때 필요한 타입을 지정할 수 있다.
function identity<T>(arg: T): T {
    return arg;
}

// 호출 시 타입을 지정
let output1 = identity<string>("Hello");
let output2 = identity<number>(42);

 

리액트에서 제네릭을 사용할 수 있는 코드로 useState를 떠올릴 수 있다.

function Component() {
  //state: string
  const [state, setState] = useState<string>('')
  //...
}

 

useState에 제네릭으로 타입을 선언하면 state 사용과 기본값 선언을 좀 더 명확하게 할 수 있다.

제네릭으로 기본값을 선언해준다면 타입스크립트가 문제를 방지해줄 수 있다.

 

 

인덱스 시그니처

  • 객체의 키를 정의하는 방식.
type Hello = {
 [key: string]: string
}

const hello: Hello = {
 hello: 'hello',
 hi: 'hi',
}

hello['hi'] // hi
hello['안녕'] // undefined

 

[key: string]을 사용한 부분이 바로 인덱스 시그니처다.

인덱스 시그니처를 사용하면 이처럼 키에 원하는 타입을 부여할 수 있다.

 

그러나 객체의 키는 동적으로 선언되는 경우를 최대한 지양해야 하고, 객테의 타입도 필요에 따라 좁혀야 한다.

 

// record를 사용
type Hello = Record<'hello' | 'hi', string>

const hello: Hello = {
 hello: 'hello',
 hi: 'hi',
}


// 타입을 사용한 인덱스 시그니처
type Hello = { [key in 'hello' | 'hi']: string }

const hello: Hello = {
 hello: 'hello',
 hi: 'hi',
}

 

Record<key, Value>를 사용하면 객체의 타입에 각각 원하는 키와 값을 넣을 수 있다.

이렇게 객체를 원하는 형태로 최대한 좁힐 수 있다.