d.ts파일

|

코딩애플강의를 보고 정리했습니다.

d.ts파일

  • 타입만 저장할 수 있는 파일형식이다.
  • 자바스크립트로 컴파일되지 않는다.
  • 타입정의만 따로 저장해놓고 import해서 사용한다.
  • 프로젝트에서 사용하는 타입을 쭉 정리해놓을 레퍼런스용으로 사용한다.

타입만 따로 d.ts파일에 작성

  1. .d.ts파일을 작성하고 타입명시
  2. 정의해둔 타입들 export 해서 사용한다.(d.ts파일은 ts파일이 아님 그렇기 때문에 글로벌타입 명시가 안된다.)
  • 파일명.d.ts라고 작성하고 다음과 같이 타입들을 명시해주면된다.
  • 참고로 함수의 경우에 파라미터,return 타입만 지정 가능하다.
export type Age = number;
export type multiply = (x: number, y: number) => number;
export interface Person {
  name: string;
}

d.ts 파일을 레퍼런스용으로 사용하기

ts파일마다 d.ts파일을 자동생성하면 된다.

// (tsconfig.json)

{
    "compilerOptions": {
        "target": "es5",
        "module": "es6",
        "declaration": true,
    }
}

tsconfig에다가 declaration 옵션을 true로 바꿔주면 된다.
그럼 저장시 자동으로 ts파일마다 d.ts 파일이 옆에 생성된다.

declare, ambient module

|

코딩애플강의를 보고 정리했습니다.

declare

.ts 파일에서 .js파일로 된 파일을 import 해오는 방법이다.

declare를 쓰면 이미 정의된 변수나 함수를 재정의할 수 있다.
(타입도 재정의 가능)

// data.js;

var a = 10;
var b = { name: 'kim' };
// (index.ts)

declare let a :number;
console.log(a + 1);
  • declare 이게 붙은 코드들은 js로 변환되지 않는다.
  • 컴파일러에게 힌트를 주는 역할만 할 뿐이다.



(참고)
declare는 자바스크립트로만 작성된 외부 라이브러리를 이용할때, 타입스크립트 버전이 없을때 사용하면 유용하다.

참고로 ts파일들은 변수만들 때 타입을 깜빡해도 자동으로 타입지정이 되어있으니 굳이 쓸 필요는없다.

tsconfig.json 안에 allowJs 옵션을 true로 켜두면 js파일도 타입지정이 알아서 implicit 하게 되니,리액트 같은 프로젝트에서 유용하다.

.ts파일에 있던 변수를 .ts파일에서 쓰고 싶으면 declare말고, 그냥 import export 문법을 쓰자.

전역으로 쓸 수 있는 파일 (Ambient Module)

타입스크립트가 제공하는 기능이다.
같은 .ts 파일끼리는 import export 없이도 타입들을 가져다 쓸 수 있는 기능이다.

// data.ts;

type Age = number;
let 나이: Age = 20;
// index.ts;

console.log(나이 + 1); //가능
let 철수: Age = 30; //가능

로컬모듈 만들기

타입스크립트 파일이 다른 .ts파일에 영향을 끼치는걸 막고싶으면 export 키워드를 추가하면된다.

import / export 키워드가 적어도 하나 있으면 그 파일은 로컬 모듈이 되고, 거기 있는 모든 변수는 export를 해줘야 다른 파일에서 사용이 가능하다.

// (data.ts)

export {};
type Age = number;
let 나이: Age = 20;
// (index.ts)

console.log(나이 + 1); //불가능
let 철수: Age = 30; //불가능

declare global

ts 파일에 import export 문법이 없으면 글로벌 모듈이 된다.

ts 파일에 import export 문법이 있으면 로컬 모듈이다.

로컬 변수에서 전역으로 변수를 만들 때 혹은 프로젝트 내의 모든 파일에서 이용가능한 타입을 만들고 싶을때 사용한다.

declare global {
  type Dog = string;
}

tuple type(array 자료에 타입지정)

|

코딩애플강의를 보고 정리했습니다.

array 자료에 타입을 지정할때

// 이런식이나,
const food: (string | number)[] = ['소고기', 25000];

// 이런식,
const food: string[] = ['소고기'];

// 혹은 이렇게..
const food: number[] = [1212];

이런식으로 지정을 해줬었는데,
tuple타입을 활용하면 좀 더 구체적으로 타입을 지정해줄수있다.

tuple type

tuple 타입은 array에 붙일 수 있는 타입인데,
자료의 위치까지 정확히 지정할 수 있는 타입이다.

Ex)

let 멍멍이: [string, boolean];
멍멍이 = ['dog', true];
  • []대괄호 안에 타입을 적어주면된다.
  • []대괄호 안에 차례로 세부 타입을 기입하면된다.
  • 첫 자료는 string,둘째 자료는 boolean만 허용해주고 다른게 들어오면 에러를 낸다.

응용 rest parameter

function 함수(...x: string[]) {
  console.log(x);
}

이런식으로 rest 파라미터를 활용해서 타입을 지정해주는게 있는데, tuple을 이용해서 타입지정이 가능하다.

Ex)tuple타입을 활용한 예..

function 함수(...x: [string, number]) {
  console.log(x);
}
함수('kim', 123); //가능
함수('kim', 123, 456); //에러
함수('kim', 'park'); //에러

tuple타입을 활용하면 rest 파라미터를 조금 더 엄격하게 사용할 수 있다.

optional chaining

tuple안에서 optional chaining적용이 가능하다.

type Num = [number, number?, number?];
let 변수1: Num = [10];
let 변수2: Num = [10, 20];
let 변수3: Num = [10, 20, 10];

하지만 아래와 코드는 에러를 낸다.

type Num = [number, number?, number];

array중간에 있는 자료는 옵션이라는게 앞뒤가 안맞기 때문인데,
그래서 ?옵션 기호는 맨 뒤에만 붙일 수 있다.
물음표 두개를 쓰고싶다면, 뒤에서 두개만 붙이는 식으로 할 수 있다.

array 두개를 spread연산자로 합칠때 타입지정

let arr = [1, 2, 3];
let arr2 = [4, 5, ...arr];

이런식의 타입지정은 아래와같이 해주면 된다.

let arr = [1,2,3]
let arr2 :[number, number, ...number[]] = [4,5, ...arr]

React + TypeScript2 Redux toolkit

|

코딩애플강의를 보고 정리했습니다. 코드위주로 정리했습니다.

리덕스는 state를 한 곳에서 관리할 수 있어서, 컴포넌트들이 props없이 state를 다루기 쉽고, 수정방법을 미리 reducer라는 함수로 정의해놔서 state수정시 발생하는 버그를 줄일 수 있어서 쓴다.
그럼 리덕스를 사용할때 타입은 어떻게 적용해줄까?

전통방식의 redux

npm install redux react-redux

import { Provider } from 'react-redux';
import { createStore } from 'redux';

interface Counter {
  count: number;
}

const 초기값: Counter = { count: 0 };

// action:any 라고 임의로 채운것임
function reducer(state = 초기값, action: any) {
  if (action.type === '증가') {
    return { count: state.count + 1 };
  } else if (action.type === '감소') {
    return { count: state.count - 1 };
  } else {
    return initialState;
  }
}

const store = createStore(reducer);

// store의 타입 미리 export 해두기
export type RootState = ReturnType<typeof store.getState>;

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

(전통방식 redux) state를 꺼낼 때

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux';
import { RootState } from './index';

function App() {
  // useSelector()파라미터에 타입지정
  const 꺼내온거 = useSelector((state: RootState) => state);
  // 타입지정
  const dispatch: Dispatch = useDispatch();

  return (
    <div className='App'>
      {꺼내온거.count}
      <button
        onClick={() => {
          dispatch({ type: '증가' });
        }}
      >
        버튼
      </button>
      <Profile name='kim'></Profile>
    </div>
  );
}

(신규방식 redux) state와 reducer 만들 때 타입지정 필요

npm install @reduxjs/toolkit

import { createSlice, configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';

const 초기값 = { count: 0, user: 'kim' };

const counterSlice = createSlice({
  name: 'counter',
  initialState: 초기값,
  reducers: {
    increment(state) {
      state.count += 1;
    },
    decrement(state) {
      state.count -= 1;
    },
    incrementByAmount(state, action: any) {
      state.count += action.payload;
    },
  },
});

let store = configureStore({
  reducer: {
    counter1: counterSlice.reducer,
  },
});

//state 타입을 export 해두는건데 나중에 쓸 데가 있음
export type RootState = ReturnType<typeof store.getState>;

//수정방법 만든거 export
export let { increment, decrement, incrementByAmount } = counterSlice.actions;

(1) state 초기값 타입지정 알아서 지정

(2) reducer 안의 action 파라미터의 타입지정

(3) 나머지는 타입지정 자동으로 된다.

action 타입지정은 방법이 따로있다.

import { createSlice, PayloadAction } from '@reduxjs/toolkit'

(상단 생략)
  incrementByAmount (state, action: PayloadAction<number>){
      state.value += action.payload
  },

나중에 dispatch할 때 보내는 데이터가 있으면, 그걸 payload라고 하는데
그 자료의 타입을 <>안에 집어넣어서 타입지정하라는 소리이다.
예를들어 문자를 payload로 보낼거면 string을 집어넣으면 된다.

(신규방식 redux) state를 꺼낼 때

import { useDispatch, useSelector } from 'react-redux';
import { RootState, increment } from './index';

function App() {
  const 꺼내온거 = useSelector((state: RootState) => state);
  const dispatch = useDispatch();

  return (
    <div className='App'>
      {꺼내온거.counter1.count}
      <button
        onClick={() => {
          dispatch(increment());
        }}
      >
        버튼
      </button>
    </div>
  );
}

state를 꺼낼때 타입지정은 state와 dispatch에 해주면 된다.

(1) useSelector()안의 파라미터에 타입을지정해주면 된다.
state가 어떻게 생겼는지 파악한 다음 타입을 알아서 지정해주거나,
타입을 index.ts이런 리듀서 만든곳에서 미리 RootState라는 타입을 export 해두면 위의 코드처럼 import해서 사용할 수 있다.

(2) useDispatch()사용할 때 타입지정이 가능하다.
예전처럼 Dispatch라는 타입을 임폴트해서 사용하던가
공식문서에서 말하는것처럼,
index.ts에서 export type AppDispatch = typeof store.dispatch 해두고,
App.tsx에서 import 해와서 useDispatch() 이렇게 타입지정해주면된다.

강사는 공식문서처럼안하고, Dispatch라는 타입을 임폴트해서 사용한다고한다.

React + TypeScript1

|

코딩애플강의를 보고 정리했습니다.

install

새롭게 설치

npx create-react-app 프로젝트명 --template typescript

기존 프로젝트에 타입스크립트만 설치

npm install --save typescript @types/node @types/react @types/react-dom @types/jest

리액트에서의 TS문법

일반 변수, 함수 타입지정

그냥 타입스크립트 배웠던 대로 똑같이 하면 된다.

JSX 타입지정

리액트에서 <div></div> 이렇게 쓰면 HTML이 아니라 JSX라고 불림

JSX.Element 사용

let 박스: JSX.Element = <div></div>;
let 버튼: JSX.Element = <button></button>;

function component 타입지정

리턴타입으로 :JSX.Element는 생략해줘도 자동으로 타입지정된다.

type AppProps = {
  name: string,
};

function App(props: AppProps): JSX.Element {
  return <div>{message}</div>;
}


참고로 아래 코드처럼, props로 JSX를 입력할 수 있게 코드를 짜는 경우도있다.

<Container a={<h4>안녕</h4>} />;

function Container(props) {
  return <div>{props.a}</div>;
}

이럴땐 JSX.IntrinsicElements 라는 이름의 타입을 사용가능하다.

<div> <a> <h4> 같은 기본 태그들을 표현해주는 타입이다.
위의 코드의 컴포넌트에 타입을 넣고 싶으면 아래처럼 해주면된다.

type ContainerProps = {
  a: JSX.IntrinsicElements['h4'],
};

function Container(props: ContainerProps) {
  return <div>{props.a}</div>;
}

이렇게 해주면 a라는 props자리에 <h4>만 넣을 수 있게 타입쉴드를 씌워놓은것이 된다.

(참고)리액트 18버전부터는 JSX.IntrinsicElements는 props 타입넣을 때만 사용가능하다.

state문법 사용시 타입 지정

state를 만들 땐 자동으로 타입이 할당되지만, state 타입이 나중에 변화할 수도 있다.(흔치않음)
이럴 때 타입을 미리 정해줄 수 있다.

const [user, setUser] = (useState < string) | (null > 'kim');

<>Generic문법을 이용해서 타입을 useState함수에 집어넣는 식으로 설정하면 된다.

type assertion 문법 사용할 때

assertion하고 싶으면, as 또는 ‘<>’쓰면 되는데, 리액트에서는 컴포넌트로 오해할 수 있어서 꺾쇠 괄호는 리액트에서 쓰지않는다.
as 키워드만 쓴다.
하지만 as키워드는 타입스크립트 보안해제기 때문에, 타입이 100확실할때만 사용하자.