Front/React

타입스크립트 개요 및 개발 환경 구성

oodada 2024. 3. 19. 10:36
반응형

타입스크립트란?

  • 2012년 마이크로소프트에서 발표한 오픈소스 프로그래밍 언어로,
  • 자바스크립트의 기반의 정적 타입 문법을 추가한 프로그래밍 언어!

타입스크립트의 특징

  1. 정적 타입의 컴파일 언어

    • 자바스크립트(동적 타입) : 변수의 타입 오류를 런타임(동작) 시점에 확인
    • 타입스크립트(정적 타입) : 변수의 타입 오류를 컴파일 시점에 확인
    • 자바스크립트로 변환(컴파일) 후 브라우저에나 Node.js 환경에서 동작

개발환경 구성

  1. ts-test 디렉토리 생성

  2. 프로젝트 생성

npm init -y
  1. 패키지 설치
  • parcel : 웹 애플리케이션 번들러
npm i -D parcel typescript
{
    "name": "ts-test",
    "version": "1.0.0",
    "description": "",
    // "main": "index.js", // 오류 발생 제거
    "scripts": {
        // 추가
        "dev": "parcel index.html",
        "build": "parcel build index.html"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "parcel": "^2.12.0",
        "typescript": "^5.4.2"
    }
}
  1. index, ts 파일 생성
ts-test
├── index.html
├── src
    ├── main.ts
├── tsconfig.json
└── package.json
  • ts 확장자를 html 파일에서 불러오기 위해 type="module" 속성 추가
  • html은 ts 파일을 브라우저에서 실행할 수 없지만 parcel이 번들링하여 실행 가능
<!-- index.html -->
<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
        <script type="module" src="./src/main.ts"></script>
    </head>
    <body></body>
</html>
  • typescript의 구성옵션을 제공하기 위해 tsconfig.json 파일 생성
npx tsc --init
// tsconfig.json
{
    "compilerOptions": {
        "target": "ES2016", // 2016년도 버전으로 자바스크립트를 타입스크립트로 변환
        "module": "ESNext", // ECMAScript의 가장 최신 버전으로 모듈을 사용
        "moduleResolution": "Node", // 모듈 해석 방식을 Node.js의 해석 방식으로 사용
        "esModuleInterop": true, // CommonJS 모듈을 ES6 모듈로 변환
        "lib": ["ESNext", "DOM"], // 사용할 라이브러리를 설정
        "strict": true // 엄격한 타입 검사를 사용
    },
    "include": ["**/*.ts", "**/*.tsx, scr/**/*.ts"], // 타입스크립트 파일을 찾을 위치
    "exclude": ["node_modules"] // 타입스크립트 파일을 제외할 위치
}
// main.ts
// let hello1: string = 123 // 오류 발생
let hello2: string = 'Hello, TypeScript!'

// hello2 = 123 // 오류 발생
hello2 = 'Hello, JavaScript!'

console.log(hello2)
  1. 개발 서버 실행
  • html은 ts 파일을 브라우저에서 실행할 수 없지만 parcel이 번들링하여 실행 가능
npm run dev
  • dist 디렉토리가 생성되고 번들링된 파일이 실행됨
  • dist > index.html 파일을 살펴보면 main.js 파일이 생성되어 있음
  • dist > main.js 파일을 살펴보면 번들링된 파일이 생성되어 있음
// let hello1: string = 123 // 오류 발생
let hello2 = 'Hello, TypeScript!'
// hello2 = 123 // 오류 발생
hello2 = 'Hello, JavaScript!'
console.log(hello2)

구문

  • 변수 선언 : let 변수명: 타입 = 값;
  • 함수 선언 : function 함수명(매개변수: 타입): 반환타입 { ... }
  • 타입 주석 : let 변수명: 타입;
  • 타입 추론 : let 변수명 = 값;
  • 타입 별칭 : type 별칭 = 타입;
  • 인터페이스 : interface 인터페이스 { ... }
  • 클래스 : class 클래스 { ... }
  • 제네릭 : function 함수명<타입>(매개변수: 타입): 반환타입 { ... }
  • 열거형 : enum 열거형 { ... }
  • 네임스페이스 : namespace 네임스페이스 { ... }
  • 모듈 : export default 모듈;
  • 데코레이터 : @데코레이터

타입 종류

  • 문자

    let str: string = '문자열'

let str: string
let blue: string = 'blue'
let primary: string = `primary color is ${blue}`
  • 숫자

    let num: number = 123

let num: number // undefined
num = 123 // 123
console.log(num)

let integer: number = 6
let float: number = 3.14
let hex: number = 0xf00d
let infinity: number = Infinity
let nan: number = NaN
  • 불리언

    let bool: boolean = true

let bool: boolean
let isTrue: boolean = true
let isFalse: boolean = false
  • 배열

    let arr: 배열타입[] = [값, 값, 값]

let arr: number[] = [1, 2, 3]
let animals: string[] = ['사자', '호랑이', '코끼리']
let empty: never[] = [] // 빈 배열
let union: (string | number)[] = ['one', 2] // 유니언 타입
let any: any[] = [1, 'two', true] // any 타입
  • 튜플 : 고정된 요소 수 만큼의 타입을 미리 선언 후 배열을 표현

    let tuple: [타입, 타입, ...] = [값, 값, ...]

let tuple: [string, number] = ['one', 1]
let person: [string, number] = ['김겨울', 30]
  • 객체

    let obj: { key: 타입, key: 타입 } = { key: 값, key: 값 }

let obj: { name: string; age: number } = { name: '김겨울', age: 30 }
let person: { name: string; age: number; etc?: boolean } = { name: '김가을', age: 30, etc: true }
  • 객체 interface

    interface 인터페이스 { key: 타입, key: 타입 }

// interface 명명규칙 : 대문자로 시작
interface IPerson {
    name: string
    age: number
    etc?: boolean
}

let userA: IPerson = { name: '김겨울', age: 3 }
let userB: IPerson = { name: '김가을', age: 2, etc: true }
  • 함수

    function 함수명(매개변수: 타입): 반환타입 { ... }

function hello(name: string): string {
    return `Hello, ${name}!`
}

console.log(hello('TypeScript')) // Hello, TypeScript!
  • 함수 타입

    let 함수명: (매개변수: 타입) => 반환타입 = (매개변수) => { ... }

let sum: (a: number, b: number) => number = function (a, b) {
    return a + b
}
let sum = function (a: number, b: number): number {
    return a + b
}
let sum: (a: number, b: number) => number = (a, b) => a + b

console.log(sum(1, 2)) // 3
// void 타입을 이용해 반환값이 없는 함수를 표현
// 반환값이 없는 함수는 undefined를 반환
const hello: () => void = function () {
    console.log('Hello!')
}
const hello: () => void = () => {
    console.log('Hello!')
}
const hello = function (): void {
    console.log('Hello!')
}

hello() // Hello!

React에서 타입스크립트 사용하기

- 프로젝트 생성

npx create-react-app react-ts --template typescript
cd react-ts
npm start
```''

-   타입스크립트를 사용하면 컴포넌트의 props와 state에 대한 타입을 지정할 수 있음

### - 컴포넌트 생성

> `const 컴포넌트명: React.FC<Props> = ({ props }) => { ... }`

#### 문법

```tsx
import React from 'react'

// Props 타입 정의
type Props = {
    name: string
}

// 컴포넌트 정의
const 컴포넌트이름: React.FC<Props> = ({ name }) => {
    return <div>Hello, {name}!</div>
}

export default Hello

예시

// src/components/Hello.tsx
import React from 'react'

type HelloProps = {
    name: string
}

const Hello: React.FC<HelloProps> = ({ name }) => {
    return <div>Hello, {name}!</div>
}

export default Hello

- useState 사용하기

const [state, setState] = useState<타입>(초기값)

// src/components/Counter.tsx
import React, { useState } from 'react'

const Counter: React.FC = () => {
    const [count, setCount] = useState<number>(0)

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => setCount(count + 1)}>+1</button>
            <button onClick={() => setCount(count - 1)}>-1</button>
        </div>
    )
}

export default Counter

- useReducer 사용하기

const [state, dispatch] = useReducer<Reducer<상태타입, 액션타입>>(reducer, 초기값)

// src/components/Counter.tsx
import React, { useReducer } from 'react'

type Action = { type: 'INCREASE' } | { type: 'DECREASE' }

function reducer(state: number, action: Action): number {
    switch (action.type) {
        case 'INCREASE':
            return state + 1
        case 'DECREASE':
            return state - 1
        default:
            throw new Error('Unhandled action')
    }
}

const Counter: React.FC = () => {
    const [count, dispatch] = useReducer(reducer, 0)

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => dispatch({ type: 'INCREASE' })}>+1</button>
            <button onClick={() => dispatch({ type: 'DECREASE' })}>-1</button>
        </div>
    )
}

export default Counter

- useContext 사용하기

const value = useContext<타입>(Context)

// src/components/Counter.tsx
import React, { useContext } from 'react'
import { CounterContext } from '../contexts/CounterContext'

const Counter: React.FC = () => {
    const { count, dispatch } = useContext(CounterContext)

    return (
        <div>
            <p>{count}</p>
            <button onClick={() => dispatch({ type: 'INCREASE' })}>+1</button>
            <button onClick={() => dispatch({ type: 'DECREASE' })}>-1</button>
        </div>
    )
}

export default Counter
반응형
티스토리 친구하기