Typescript - 11

hoin_lee·2023년 8월 3일
0

TypeScript

목록 보기
12/14

타입선언

.ts가 아닌 .d.ts의 형식이 타입 선언 파일이며 특별한 용도로 사용된다.
해당 파일에선 구현 세부 사항이나 실행될 JS 코드, 출력 같은 걸 찾아볼 순 없다
대신 타입 정보를 찾을 수 있는데 즉 타입을 선언하는 것이다
typescript가 확인하고 코드에 대한 타입 규칙을 이해하고 실행하는데 사용한다

제 3자 라이브러리 사용하기 - Axios

가장 먼저 간단하게 볼 것은 Axios인데

import axios from 'axios'

axios

axios를 npm으로 설치하고 직접 import한 후 코드로 입력하고 .을 찍어보면 자동완성이 죽 뜰것이다
그럼 문제가 없다는 뜻인데 왜 그럴까 하면 axios에 마우스를 올리면 타입 파일들을 확인하러 갈 수 있다.
이처럼 최근엔 라이브러리에 typescript를 선언파일들을 적용해서 주는 라이브러리들이 많지만 또 아닌 곳도 많다
예시 다루기

import axios from 'axios'

axios.get("url").then((res)=>{
	console.log("success")
}).catch((e)=>{
	console.log("error",e)
})

딱히 javascript를 사용할 때와 크게 달라진 건 없다. typescript는 javascript와 거의 같지만 타입 검사등의 도움을 주기 때문
인수를 누락하거나, res.를 사용할 때 철자가 틀리거나 AxiosResponse타입에는 그런게 없다고 알려주며 힌트도 제공한다
선언 파일을 보면 제네릭을 사용하고 있는데

import axios from 'axios'

axios.get<해당타입>("url").then((res)=>{
	console.log("success")
}).catch((e)=>{
	console.log("error",e)
})

get 뒤에 <>문법으로 response될 타입을 넣게되면(interface로 객체로 만들어도 되고 반환 되는 데이터타입 그대로를 만들어서 넣어주면 된다) 반환 데이터 타입은 해당 타입을 따라가게 된다

타입 개별 설치

Lodash와 같은 제 3자 라이브러리는 타입스크립트르 선언파일을 함께 제공하지 않는데

// ~~~.ts 
import _ from "lodash" //에러 발생

'모듈 lodash에 대한 선언 파일을 찾을 수 없습니다'와 같은 에러가 발생한다. import부터!
lodash가 설치되지 않거나 찾을 수 없다는 뜻은 아니다
lodash는 찾았지만 타입 선언 파일이 없다는 뜻이다

즉, typescript에서 lodash를 사용하려면 해당 타입 선언을 다른 곳에서 찾아야 한다
거의 모든 유명한 라이브러리들과 제 3자 javascript 도구들은 거의 찾을 수 있다
그래서 공식문서에도 나왔듯이 npm으로 설치해주면 되는데

npm install --save-dev @types/lodash를 입력해주면된다.
여기서 --save-dev는 프로덕션 단계에선 굳이 타입스크립트가 필요하진 않을테니 개발단계인 dev에서 사용하는 것
그럼 설치 하면 위에서 나온 선언 파일을 찾을 수 없다는 에러는 사라진다

모듈

네임스페이스에 대한 메모

현재는 javascript의 ES모듈이 나왔기 때문에 typescript 공식문서에서도 javascript의 환경에 맞춰서 사용하라며 거의 쓰지 않아지고 있다
다만 네임스페이스가 쓰이는 한 가지 경우가 있는데 DefinitelyTyped 리포지토리이다
과거에는 많이 사용되어 왔으니 작업 해 놓은 것들은 아마 namespace를 사용했고 계속 남아있을 것이다.
현재 우리가 작성할 프로젝트에선 사용할 일이 없겠지만 알아두는 것이 좋다

//utils.ts
function add(x:number, y:number){
  return x+y
}
function sample<T>(arr:T[]):T {
  const idx = Math.floor(Math.random() * arr.length);
  return arr[idx];
}

만약 utils 파일에 있는 코드를 공유하고 다른 위치로 요청하거나 가져오기를 해야한다

//index.ts
add(3,4)
sample<number>([2,3,4,2])

??에러가 안난다! 왜그럴까?
막 코드를 배워서 배운대로 따라할 댄 export를 시켜 모듈화를 했어야 했다 하지만 그냥 디렉토리 안에 파일 2개 만들고 사용하는데 export도 없는데 사용이 된다.

일단 주어진 addsample은 모듈이 아니다. export가 붙어있지 않다(최상위 awiat도 없다)
다만, 스크립트 안에서 작업할 때 변수와 타입은 공유 전역 스코프 내부에 있다고 선언된다
그러므로 현재 addsample함수는 모두 공유 전역 스코프에 있는 것

모듈로 작업하지 않아서 모두 전역 스코프 안에 들어가 있다
이게 바로 모듈의 특징이다 우리가 코드르 ㄹ분리 및 구성하고 다른 네임스페이스를 가질 수 있게 해준다
그럼 export,import를 해서 사용해보자

모듈 사용

위에서 말했다 싶이 export또는 최상위 await를 사용하지 않으면 전역 스코프 내부에 있다고 판단한다 했는데 이럴 경우 프로젝트 규모가 커지고 다른 파일과 같은 이름의 함수를 정의한다면 굉장한 혼란을 야기할 수 있다

하지만 export 키워드를 넣을경우 typescript는 우리가 모듈에서 작업한다고 인식한다

//utils.ts
export function add(x:number, y:number){
  return x+y
}
export function sample<T>(arr:T[]):T {
  const idx = Math.floor(Math.random() * arr.length);
  return arr[idx];
}

이렇게 작성해보고 index.ts로 돌아가보면

//index.ts
add(3,4) // 찾을 수 없다는 에러 발생
sample<number>([2,3,4,2])// 찾을 수 없다는 에러 발생

typescript는 모듈모드(ES 모듈 모드)로 전환되어 각 파일이 각자 독립된 파일과 네임스페이스로 분리되어 공유하려는 함수 기능을 일일이 가져오고 내보내야 한다

//index.ts
import {add,sample} from "./utils.js"

add(3,4) // 찾을 수 없다는 에러 발생
sample<number>([2,3,4,2])// 찾을 수 없다는 에러 발생

이렇게 import 시켜주면 된다. 이때 from뒤에오는 파일이름 확장자는 .js일까 .ts일까?
.ts로 하면 에러가 생기고 .js로 생기면 에러가 없다. 결국 javascript로 컴파일 되기 때문이고 typescript도 어떻게 처리할지 이미 인식하고 있기 때문

하지만 브라우저에서 출력하기 위해 index.html을 만들고 실행햇더니 export때문에 에러가 난다
그러면 아까처럼 전역으로 써야할까? 아까 나왔던 얘기처럼 프로젝트가 커지고 의존성이 서로 엮이면 매우 혼란스러워진다.
그럼 ES모듈처럼 사용할 수 있게 해달라고 typescript에게 컴파일 할때 그렇게 만들어달라 해야하는데
tsconfig.json 파일에 들어가 "module"설정을 찾아보자. 찾아보면
"module" : "commonjs" 이렇게 입력되어 있는데 때문에 require 모듈과 같은 브라우저에서는 동작하지 않는 내보내기 기능들을 사용할 수 없는것이다.

"module" : "ES6" 로 변경하거나 ES로 시작하는 것들을 사용하면 된다
그러면 끝났을까? 브라우저로 가서 확인해보니
모듈 외부에서 import 문을 사용할 수 없다라고 에러를 내뱉는다!

이는 브라우저에서 모듈을 쓸 때 흔히 생기는 오류로 최근 브라우저들은 모듈 구문을 지원하기는 하지만 ES모듈, 가져오기와 내보내기는 최신 브라우저에서만 사용할 수 있어 다른 오류가 발생할 수도 있다

쨌든 그리고 index.html에서 추가한 스크립트 파일 코드에 모듈의 타입을 특정해줘야 한다
<script type="module" src="./index.js"></script> 이렇게 고쳐준다.
이후 서버를 작동하고 브라우저를 열어보면 동작을 확인할 수 있다

타입 가져오기(import)

변수나 함수뿐만 아니라 작성한 타입또한 공유할 수 있는데

// types.ts
export interface Person{
  username:string;
  email:string;
}

export type Color = "red" | "green" | "blue"

이렇게 다른 파일에 interfacetype별칭을 통해 타입을 만들었고 export로 내보냈다. 다른 파일에서도 사용가능할까?

// User.ts
import {Person, Color} from "./types.js"

export default class User implements Person {
//some code...
}

이후 컴파일하면?? types.js를 확인하면 export{}말고 전부 사라졌다
모듈로 선언하는 코드만 남았다
하지만 타입을 작성한대로 User.js에는 컴파일 되어 있다. Typescript 우리가 원하는 방향대로 동작했지만 Babel같은 트랜스 파일러를 사용하면 타입을 가져올 때 문제가 생길 수 있다
때문에 3.8버전부터는 typescript 자체에서 사용할 수 있는 import 구문을 제공하는데

import type {Person, Color} from "./types.js"

import 뒤에 내보낼 타입을 작성하는 것이다.
이는 javascript에서 import type은 무조건 사라진다 라고 공식문서에 있으며 Babel같은 도구로도 코드를 더 쉽게 파악할 수 있으며 타입을 가져오는 훨씬 더 안전한 방법이 된다

profile
https://mo-i-programmers.tistory.com/

0개의 댓글