타입스크립트 사용하기
TypeScript는 타입 정의를 추가해 JavaScript를 확장한 언어이다. 새로운 React Native 프로젝트는 기본적으로 TypeScript를 타겟으로 하지만, JavaScript와 Flow도 지원한다.
TypeScript 시작하기
React Native CLI로 생성한 새 프로젝트나 Ignite와 같은 인기 템플릿은 기본적으로 TypeScript를 사용한다.
Expo에서도 TypeScript를 활용할 수 있다. Expo는 TypeScript 템플릿을 제공하며, 프로젝트에 .ts
또는 .tsx
파일을 추가하면 자동으로 TypeScript를 설치하고 설정한다.
npx create-expo-app --template
기존 프로젝트에 TypeScript 추가하기
- 프로젝트에 TypeScript, 타입 정의, ESLint 플러그인을 설치한다.
- npm
- Yarn
npm install -D @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
yarn add --dev @tsconfig/react-native @types/jest @types/react @types/react-test-renderer typescript
이 명령어는 모든 의존성의 최신 버전을 추가한다. 프로젝트에서 사용 중인 기존 패키지와 버전을 맞추기 위해 버전을 조정해야 할 수도 있다. React Native Upgrade Helper와 같은 도구를 사용해 React Native에서 제공하는 버전을 확인할 수 있다.
- TypeScript 설정 파일을 추가한다. 프로젝트 루트에
tsconfig.json
파일을 생성한다:
{
"extends": "@tsconfig/react-native/tsconfig.json"
}
- JavaScript 파일을
*.tsx
로 변경한다.
./index.js
엔트리포인트 파일은 그대로 두어야 한다. 그렇지 않으면 프로덕션 빌드를 번들링할 때 문제가 발생할 수 있다.
tsc
를 실행해 새로운 TypeScript 파일의 타입을 검사한다.
- npm
- Yarn
npx tsc
yarn tsc
TypeScript 대신 JavaScript 사용하기
React Native는 새로운 애플리케이션을 기본적으로 TypeScript로 설정한다. 하지만 여전히 JavaScript를 사용할 수 있다. .jsx
확장자를 가진 파일은 TypeScript가 아닌 JavaScript로 처리되며, 타입 검사를 수행하지 않는다. JavaScript 모듈은 TypeScript 모듈에서 여전히 가져올 수 있고, 그 반대도 가능하다.
TypeScript와 React Native의 동작 방식
기본적으로 TypeScript 소스 코드는 번들링 과정에서 Babel에 의해 변환된다. TypeScript 컴파일러는 타입 검사만을 위해 사용하는 것을 권장한다. 이는 새로 생성된 애플리케이션에서 tsc
의 기본 동작이다. 기존의 TypeScript 코드를 React Native로 이식하는 경우, TypeScript 대신 Babel을 사용할 때 주의해야 할 사항이 있다.
React Native + TypeScript의 모습
React 컴포넌트의 Props와 State에 인터페이스를 제공하려면 React.Component<Props, State>
를 사용한다. 이렇게 하면 JSX에서 해당 컴포넌트를 작업할 때 타입 검사와 에디터의 자동 완성 기능을 활용할 수 있다.
import React from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';
export type Props = {
name: string;
baseEnthusiasmLevel?: number;
};
const Hello: React.FC<Props> = ({
name,
baseEnthusiasmLevel = 0,
}) => {
const [enthusiasmLevel, setEnthusiasmLevel] = React.useState(
baseEnthusiasmLevel,
);
const onIncrement = () =>
setEnthusiasmLevel(enthusiasmLevel + 1);
const onDecrement = () =>
setEnthusiasmLevel(
enthusiasmLevel > 0 ? enthusiasmLevel - 1 : 0,
);
const getExclamationMarks = (numChars: number) =>
numChars > 0 ? Array(numChars + 1).join('!') : '';
return (
<View style={styles.container}>
<Text style={styles.greeting}>
Hello {name}
{getExclamationMarks(enthusiasmLevel)}
</Text>
<View>
<Button
title="Increase enthusiasm"
accessibilityLabel="increment"
onPress={onIncrement}
color="blue"
/>
<Button
title="Decrease enthusiasm"
accessibilityLabel="decrement"
onPress={onDecrement}
color="red"
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
greeting: {
fontSize: 20,
fontWeight: 'bold',
margin: 16,
},
});
export default Hello;
이 문법에 대해 더 자세히 알아보려면 TypeScript 플레이그라운드를 확인해 보자.
유용한 조언을 찾을 수 있는 곳
- TypeScript 핸드북
- TypeScript와 함께 React 사용하기 (React 공식 문서)
- React + TypeScript 치트시트는 React와 TypeScript를 함께 사용하는 방법에 대한 좋은 개요를 제공한다.
타입스크립트에서 커스텀 경로 별칭 사용하기
타입스크립트에서 커스텀 경로 별칭을 사용하려면 Babel과 타입스크립트 양쪽에서 설정해야 한다. 방법은 다음과 같다:
tsconfig.json
파일을 수정해 커스텀 경로 매핑을 추가한다.src
루트에 있는 파일은 경로 참조 없이 사용할 수 있게 하고, 테스트 파일은tests/File.tsx
로 접근할 수 있게 설정한다:
{
- "extends": "@tsconfig/react-native/tsconfig.json"
+ "extends": "@tsconfig/react-native/tsconfig.json",
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "*": ["src/*"],
+ "tests": ["tests/*"],
+ "@components/*": ["src/components/*"],
+ },
+ }
}
- 프로젝트에
babel-plugin-module-resolver
를 개발용 패키지로 추가한다:
- npm
- Yarn
npm install --save-dev babel-plugin-module-resolver
yarn add --dev babel-plugin-module-resolver
- 마지막으로
babel.config.js
를 설정한다 (babel.config.js
의 문법은tsconfig.json
과 다르다는 점에 유의한다):
{
presets: ['module:metro-react-native-babel-preset'],
+ plugins: [
+ [
+ 'module-resolver',
+ {
+ root: ['./src'],
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
+ alias: {
+ tests: ['./tests/'],
+ "@components": "./src/components",
+ }
+ }
+ ]
+ ]
}