실전 TypeScript - 4

2021. 7. 4. 21:09프로그래밍/Typescript

728x90

오늘도 나를 꼴받게 만드는 에러가 하나 있었다.
그런데 이 내용이 TypeScript의 나름 아이덴티티에 해당하는 부분이라 한번 가져와봤다.


문제 상황

// pageStyles.json
{
  "root": {
    "position": "absolute",
    "top": "50%",
    "transform": "translateY(-50%)"
  }
}

// HomePage.json
import { makeStyles } from '@material-ui/core/styles';
import { pageStyles } from '../styles';

const useStyles = makeStyles({ 
  ...pageStyles,
 });

const HomePage:React.FunctionComponent<PageManagerProps> = () => {
  const classes = useStyles();
  
  return (
    <div className={classes.root} />
  )
}

pageStyles라는 CSS내용이 적힌 json을 만들고, makeStyles에 해체 방식을 사용하여 대입하였다.

그런데 이런 문제가 생긴다.

Argument of type '{ root: { position: string; top: string; transform: string; }; }' is not assignable to parameter of type 'Styles<Theme, {}, "root">'.
  Type '{ root: { position: string; top: string; transform: string; }; }' is not assignable to type 'StyleRules<{}, "root">'.
    Types of property 'root' are incompatible.
      Type '{ position: string; top: string; transform: string; }' is not assignable to type 'CSSProperties | CreateCSSProperties<{}> | PropsFunc<{}, CreateCSSProperties<{}>>'.
        Type '{ position: string; top: string; transform: string; }' is not assignable to type 'CreateCSSProperties<{}>'.
          Types of property 'position' are incompatible.
            Type 'string' is not assignable to type 'PositionProperty | PropsFunc<{}, PositionProperty | undefined> | undefined'.ts(2345)

ㅋㅋ 에러를 이딴식으로 뱉는데 어떻게 코드를 짜냐고 ㅋㅋ


문제 해결 과정

우선 단서는 에러 로그의 맨밑줄이다. 로그 스택상 가장 아래가 가장 문제의 본질에 가깝다.

Type 'string' is not assignable to type 'PositionProperty | PropsFunc<{}, PositionProperty | undefined> | undefined'.ts(2345)

뭔가가 지금 string인데, 'PositionProperty | ...'에 맞지 않는다고 한다.
Position으로 시작하는 것을 보니, CSS의 position에 대한 부분인 것 같다.

그렇다면 이 PositionProperty를 찾아보자.

https://use-form.netlify.app/modules/_node_modules_csstype_index_d_.html#positionproperty

 

"node_modules/csstype/index.d" | typescript

 

use-form.netlify.app

PositionProperty: Globals | "-webkit-sticky" | "absolute" | "fixed" | "relative" | "static" | "sticky"

그렇다. 이 7가지에 속하지 않으면 안되는 것이다.

근데, 현재 position은 "absolute"로 되어있다. 그런데 왜 에러가 뜰까?

그것은 바로, "absolute"의 타입은 string이기 때문이다.
그럼 저 PositionProperty의 "absolute"의 타입은 뭘까?

바로 "absolute"다.
엥? 그렇다. "absolute" 값의 타입은 바로 string이 아닌 상수(const)인 "absolute"이다.

자세한 내용은 TypeScript Handbook > literal interface를 살펴보자.

https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-inference

 

Documentation - Everyday Types

The language primitives.

www.typescriptlang.org


문제 해결

자, 그렇다면 해야 할 방법은 간단하다. "absolute"의 type을 바꿔버리는 것이다.

// pageStyles.tsx
export default {
  "root": {
    "position": "absolute" as const,
    "top": "50%",
    "transform": "translateY(-50%)"
  }
}

pageStyles 파일을 json에서 tsx로 바꾸고, position의 값을 상수로 만들었다.

이런 방법도 된다.

"position": "absolute" as "absolute",

마무리하며

이러한 사소한 내용들이 TypeScirpt에 대한 이해도를 가르는 내용이 아닐까 싶다.

전이었으면 대충 검색해서 이것저것 대입해보면서 하겠지만,

이제 이해하고 원인을 찾아 해결하게 되었다.

이게 공식 문서를 정독하는 이유가 아닐까 싶다.

'프로그래밍 > Typescript' 카테고리의 다른 글

Typescript로 하는 React Context 잡기술  (0) 2021.09.14
실전 TypeScirpt 5  (0) 2021.07.05
실전 TypeScript 2  (0) 2021.07.02
근황 & 실전 TypeScript 1  (0) 2021.07.01
TypeScript - Handbook (Modules)  (0) 2021.06.23