CRA
[프로젝트 구조]
[package.json] - 빨간색 줄들이 TS 프로젝트에 추가되어 있음.
[tsconfig.json]
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
[프로젝트 구조]
[스토리북 실제 화면] 왼쪽 : JS, 오른쪽 : TS
# package.json
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
# or
yarn add typescript @types/node @types/react @types/react-dom @types/jest
//tsconfig.json
{
"compilerOptions": {
"baseUrl": "src/",
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react", //
"esModuleInterop": true
},
"include": [
"src"
],
"exclude": [
"**/*.test.ts",
"**/*.test.tsx"
]
}
관련 에러 해결
- [디버깅] Cannot use JSX unless the '--jsx' flag is provided.ts(17004) 해결****
참고 링크 : https://steadily-worked.tistory.com/632
해결 법 : tsconfig.json 의 “jsx” : “react-jsx” 를 “react” 로 변경- (React) Argument type 'HTMLElement or null' not assignable to parameter type 'Element or DocumentFragment' 에러
해결법 1 : tsconfig.json 의 “strict” : “true” 를 “false” 로 변경 (스트릭트 모드 사용 X 방법)
해결법 2 : index.tsx 에서
const root = ReactDOM.createRoot(document.getElementById('root')) 를
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
로 타입을 지정
스토리북 컴포넌트 jsx → tsx 변환 (스토리북 빌드시 제공된 예시 Button 가지고 비교)
1) Button.jsx 의 확장자를 tsx로 바꾸고, propTypes로 정의된 Prop를 Interface로 타입을 지정해준다.
// JSX 방식
import PropTypes from 'prop-types';
Button.propTypes = {
primary: PropTypes.bool,
backgroundColor: PropTypes.string,
size: PropTypes.oneOf(['small', 'medium', 'large']),
label: PropTypes.string.isRequired,
onClick: PropTypes.func,
};
// TSX 방식
interface ButtonProps {
primary?: boolean;
backgroundColor?: string;
size?: 'small' | 'medium' | 'large';
label: string;
onClick?: () => void;
}
jsx에서 any타입에 지정해두지 않은 속성을 받았다면, prop 설정에서 props를 옵셔널(?)를 붙여주도록 하자.( 위 타입스크립트 프롭스의 primary, size, onClick)
jsx의 defaultProps 값은 실제 컴포넌트의 프롭스에서 값을 지정해준다
// JSX
Button.defaultProps = {
backgroundColor: null,
primary: false,
size: 'medium',
label: '',
onClick: undefined,
};
export const Button = (
{ primary,
backgroundColor,
size,
label,
...props }) => {
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
return (
<button
type="button"
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
style={backgroundColor && { backgroundColor }}
{...props}
>
{label}
</button>
);
};
// TSX
export const Button = ({
primary = false,
size = 'medium',
backgroundColor,
label,
...props
}: ButtonProps) => {
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
return (
<button
type="button"
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
style={{ backgroundColor }}
{...props}
>
{label}
</button>
);
};