.ts
가 아닌 .d.ts
의 형식이 타입 선언 파일이며 특별한 용도로 사용된다.
해당 파일에선 구현 세부 사항이나 실행될 JS 코드, 출력 같은 걸 찾아볼 순 없다
대신 타입 정보를 찾을 수 있는데 즉 타입을 선언하는 것이다
typescript가 확인하고 코드에 대한 타입 규칙을 이해하고 실행하는데 사용한다
가장 먼저 간단하게 볼 것은 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
도 없는데 사용이 된다.
일단 주어진 add
와 sample
은 모듈이 아니다. export
가 붙어있지 않다(최상위 awiat
도 없다)
다만, 스크립트 안에서 작업할 때 변수와 타입은 공유 전역 스코프 내부에 있다고 선언된다
그러므로 현재 add
와 sample
함수는 모두 공유 전역 스코프에 있는 것
모듈로 작업하지 않아서 모두 전역 스코프 안에 들어가 있다
이게 바로 모듈의 특징이다 우리가 코드르 ㄹ분리 및 구성하고 다른 네임스페이스를 가질 수 있게 해준다
그럼 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>
이렇게 고쳐준다.
이후 서버를 작동하고 브라우저를 열어보면 동작을 확인할 수 있다
변수나 함수뿐만 아니라 작성한 타입또한 공유할 수 있는데
// types.ts
export interface Person{
username:string;
email:string;
}
export type Color = "red" | "green" | "blue"
이렇게 다른 파일에 interface
와 type
별칭을 통해 타입을 만들었고 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같은 도구로도 코드를 더 쉽게 파악할 수 있으며 타입을 가져오는 훨씬 더 안전한 방법이 된다