왜 typescript에서 string을 줄이지 않으세요?

HG·2024년 5월 29일
0

why

목록 보기
3/3

Type은 최대한 구체적이어야한다.

그렇지 않으면 typescript를 쓸 필요가 없다.
ts를 쓸 때, any를 큰 으로 여긴다.
그러나, 그만큼이나 적폐인건 string, Object, Function이다.
ObjectFunctionstring 만큼 많이 안쓰기 때문에 다루지 않겠다.

ts를 왜 쓸까?

정적분석을 위해서이다.

타입스크립트 공식문서
TypeScript is JavaScript’s runtime with a compile-time type checker

공식문서에서도 말하듯이 typescript는 그냥 javascript의 정적 타입 검사자이다.
정적분석을 한다는건 엄청나게 대단한 요소이다.

코드를 실행하기 전에 정적인 환경에서 미리 에러를 발견할 수 있음과 동시에
정적 분석을 하기 때문에 극적인 intellisense를 활용할 수 있다.

오늘 알아볼건, type을 string으로 했을때 어떤 문제들이 발생할 수 있는지 알아보자

ex) 지도를 관리할때 info를 담은 state를 관리하는 훅을 하나 만들었다고 생각하자
info의 state에는 zoom, center, mapState, cursor를 담을 것이다.

interface MapInfoState {
  zoom: number;
  center: [number,number];
  mapState: string;
  cursor: Object;
}

export const useMapInfo = () => {
  const state:MapInfoState = {
    zoom: 5,
    mapState: "idle",
    center: [0, 0],
    cursor: { style: "none", text: "" },
  };

  const setState = <Key extends keyof MapInfoState>(key: Key, value: MapInfoState[Key]) => {
    state[key] = value;
  };

  return {
    state,
    setState,
  };
}

이런식으로 코드를 짰다면? 어떤부분에서 문제가 발생할까?

setState를 한다고 생각해보자

const mapInfo = useMapInfo() 
mapInfo.setState('mapState','???')
mapInfo.setState('cursor',{})

여기서 아무런 문제가 발생하지 않는다. 즉 이 코드를 사용하는 입장에서 useCase를 확인하던가, 아니면 소스를 추적하면서, 어떤값이 들어갈 수 있는지 확인해야한다.

그렇다면 어떻게 개선할 수 있을까?

현재의 Map의 상태를 나타내는 MapState같은 경우의 타입은 미리 지정할 수 있다.
그리고 그렇게 사용을 하기를 권장할 것이다.
예를들어 미리 타입을 "idle" | "loading" | "success" | "error"만 가능하다고 지정해 놓는다면,
Cusrosr의 State가 될 수 있는게 { style: "none"; text: "" } | { style: "pointer"; text: string } 라고 미리 지정을 해놓는다면 어떤 이점이 생길까?

type MapState =  "idle" | "loading" | "success" | 'error';
type CursorState = { style: "none"; text: "" } | { style: "pointer"; text: string };

interface MapInfoState {
  zoom: number;
  center: [number,number];
  mapState: MapState;
  cursor: CursorState;
}

export const useMapInfo = () => {
  const state:MapInfoState = {
    zoom: 5,
    mapState: "idle",
    center: [0, 0],
    cursor: { style: "none", text: "" },
  };

  const setState = <Key extends keyof MapInfoState>(key: Key, value: MapInfoState[Key]) => {
    state[key] = value;
  };

  return {
    state,
    setState,
  };
}

의 형식으로 코드를 작성하고

const mapInfo = useMapInfo() 
mapInfo.setState('mapState','???')
mapInfo.setState('cursor',{})

바로 오류가 발생한다.
Argument of type '"???"' is not assignable to parameter of type 'MapState'.(2345)
Argument of type '{}' is not assignable to parameter of type 'CursorState'.(2345)
이러한 union type을 통한 type safe를 가능하게 할 수 있다.
vscode 기준으로

const mapInfo = useMapInfo() 
mapInfo.setState('mapState','여기')

여기 에 들어갈 부분을 스페이스바로만 찾아가면서 코드를 작성하는건 꽤나 짜릿한 경험이다.

물론 이건 코드를 작성하는 과정에서의 문제이고, 로직을 실행하는 부분에서는 이렇게 하지 않고 좀 더 안전하게 ts-pattern같은 라이브러리를 활용하면 더 좋은 결과를 만들 수 있을 것 같다.

profile
Making Body, Making Food, Making Co?de

0개의 댓글