본문 바로가기

FrontEnd

[typescript] d.ts 파일을 js 프로젝트에서 사용할 수 있을까?

반응형

typescript

.d.ts 파일을 js 프로젝트에서 사용할 수 있을까요?

js 개발자의 타입 안전성을 보장하면서 말입니다.

아래 페이지의 스크립트를 이용하여 js 파일의 대략적인 타입을 .d.ts 파일로 추출한뒤, .d.ts의 타입을 좀 더 상세하게 작성했습니다.

https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html

 

Documentation - Creating .d.ts Files from .js files

How to add d.ts generation to JavaScript projects

www.typescriptlang.org

npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types

.d.ts 파일을 .js 파일과 같은 위치에 위치시킨 뒤, ts 파일에서 임포트 하면 타입 완성이 잘 됩니다.

즉 .d.ts는 ts 프로젝트를 위한 헤더 역할을 수행합니다.

하지만 .d.ts의 대상이 되는 js 파일에서는 타입 완성이 되지 않는 것을 볼 수 있었습니다.

 

a.js:

export function abc( x, y ) { return !!(x-y)}

a.d.ts:

export declare function abc(x: number, y: number): boolean;

b.js:

import { abc } from './a'

기대 효과 :

a.js와 b.js 내에서 abc의 타입은 (num, num) => boolean 😱 😱 😱

실제 효과 : 

  • a.js > (any, any) => void
  • b.js > (number, number) => boolean

생각한 대로 js에서 타입 완성이 되지 않습니다. 

저와 같은 생각을 한 사람이 없었을 리가 없었습니다.

TL;DR : .d.ts와 js를 매핑하는 것은 기술적으로 간단하지 않으므로, 해당 기능이 필요하면 jsDoc을 쓰세요

https://github.com/microsoft/TypeScript/issues/14342

 

Use d.ts specified types within a JavaScript Module Itself · Issue #14342 · microsoft/TypeScript

From microsoft/vscode#21454 TypeScript Version: 2.2.1 Code For a javascript project a.js: export function abc( x, y ) { } a.d.ts: export declare function abc(x: number, y: number): boolean; b.js im...

github.com

.d.ts에서 .js 파일로의 매핑은 간단하지 않습니다.
예를 들어 Class입니다.
해당 기능은 ES6 미만에는 존재하지 않기 때문에 소스와 타입의 1대1 매핑이 어렵습니다.

즉, .d.ts 파일은 js 파일을 ts에서 컨슘하려는 사용자를 위해 존재하는 헤더 파일과 같은 역할을 합니다.

따라서 js 파일의 .d.ts 파일을 이용한 타입 체크는 간단하지 않습니다.


Workaround

하지만 위 링크에서도 언급하였듯이 전혀 방법이 없는 것은 아닙니다.

https://github.com/microsoft/TypeScript/issues/14377

 

[Salsa] Provide a JSDoc equivalent of `import { ..} from "mod"` · Issue #14377 · microsoft/TypeScript

Given an implementation of a class: // file.js export default class File { ... } How can you use the type without importing the module: // another export default Util { /** @param {File} file */ ge...

github.com

아래와 같이 jsDoc과 .d.ts 기능을 섞어서 사용하면 됩니다.

지금으로서는 js 파일의 오염을 최소화 하는 가장 간단한 방법인 듯 합니다.

사람의 공수가 좀 들어가야하는 단점이 있습니다.

babel을 이용해서 어느 정도 자동화 할 수 있는지 조사해 볼 예정입니다.

/** @type {import("./a").a} */
export function abc( x, y ) { return !!(x-y)}

올바른 구현
잘못된 구현

비슷하게 동작하는 바벨 플러그인

export default function (babel) { 
  return {
    name: "ast-transform", // not required
    visitor: {
      FunctionDeclaration(path) {
        path.parentPath.addComment("leading",`* @type{import("./${path.node.id.name}"}.${path.node.id.name}`);
      }
    }
  };
}

참고

https://medium.com/homeday/confident-js-series-part-2-types-jsdocs-and-declaration-files-23ec2df6c47

 

Confident JS series: Part 2 — Types, JSDocs, and declaration files

Using TypeScript without TypeScript

medium.com

https://www.detroitlabs.com/adding-custom-type-definitions-to-a-third-party-library/

 

Adding Custom Type Definitions to a Third-Party Library — Detroit Labs

Karen FordPosts by Karen FordIf you’re like me, you may not always want to write your own code for every little thing, and you may choose to add a third party library into your React/Angular/other-js-framework app. If you’ve done this, […]

www.detroitlabs.com

https://www.staging-typescript.org/docs/handbook/declaration-files/dts-from-js.html

 

Documentation - Creating .d.ts Files from .js files

How to add d.ts generation to JavaScript projects

www.staging-typescript.org

 

반응형