본문 바로가기

FrontEnd

javascript 프로젝트에 d.ts를 이용하여 타입스크립트 도입하기

반응형

javascript를 메인으로 사용하는 프로젝트에

사정상 코드베이스를 타입스크립트로 마이그레이션 할 수 없을 때,

d.ts를 통해 타입스크립트의 힘을 활용하는 방법을 알아봅니다.

해당 내용은 사내에서 프로젝트를 진행하며 배운 내용을 정리한 것임을 말씀드립니다.

d.ts파일이란?

기본적으로 c언어의 header와 같은 역할을 합니다.

즉 각 모듈(파일)에 대한 인터페이스 역할만 하지, 모듈 내부의 타입 안정성에 대해서는 전혀 보장해주지 않습니다.

하지만 d.ts파일을 js파일의 타입 체킹에 이용할 수 있습니다.

[Front, 2022-09-14] Typescript d.ts 파일을 js 프로젝트에서 사용할 수 있을까?


d.ts 파일의 타입 선언 활용하기

d.ts 파일 내부에서는 타입 선언과 변수, 함수 선언을 사용할 수 있습니다.

구현은 내버려 두고, 해당 타입의 변수가 존재한다고 가정합니다.

중요한 것은 타입을 export 하는 것이 아니라 변수(선언)을 export 해야 다른 파일에서 해당 모듈을 활용할 수 있습니다.

export type MyModule ={}; // x
export declare const MyModule: MyType ; // O
 

네임스페이스와 같은 구 방식도 존재하지만, declare const와 내부 필드 선언으로 대체 가능합니다.

(그리고 더 직관적입니다.)

// MyModule.js
/**@type{import("./Counter").default} */
const Counter = { Container, ControlContainer, ControlButton };

// MyModule.d.ts
declare const Counter = {Container,ControlContainer,ControlButton};

 

d.ts 파일과 리액트 프로젝트

리액트 컴포넌트의 경우 함수 필드에 하위 컴포넌트를 추가하는 방식으로 컴파운드 컴포넌트 패턴을 자주 구현합니다.

이 경우 익명 함수로 컴포넌트를 구현할 경우 타입 오류가 발생합니다.

default에 해당하는 함수는 function으로 변경해 줍니다.

// MyModule.js
/**@type{import("./Counter").default} */
function MyFunction(){//...//}
MyFunction.SubConmponent = ()=><></>

// MyModule.d.ts
declare function MyFunction():JSX.Element;
declare function SubCmponent():JSX.Element;
MyFunction['SubConmponent']= SubCmponent;

d.ts 파일과 propTypes

프로젝트 전체를 타입스크립트로 마이그레이션 하는 것이 아니면,

특히 stroybook을 사용하는 경우, propTypes를 사용하는 것이 좋습니다.

이 경우 propTypes와 함수의 시그니처를 동기화 할 수 있습니다.

// MyModule.d.ts

declare function MyComponenent(props:MyProp):JSX.Element;

declare const MyComponenentPropTypes : React.WeakValidationMap<
Partial<Parameters<typeof MyComponent>[0]>
>;

// or ...
declare const ControlButtonPropTypes : React.WeakValidationMap<
MyProp
>;

MyComponenent['propTypes'] = ControlButtonPropTypes;

코드 내에서 타입 단언(assertion)

js 코드 내에서 디폴트 값을 사용할 경우, 타입스크립트 컴파일러는 리터럴 유니온 타입을 string으로 추론합니다.

이 경우 타입 단언이 필요한데, 아래와 같이 인라인 타입 주석을 추가하고, 오른쪽을 ()로 감싸주면 됩니다.

 
// MyModule.ts

// before
function ControlButton({
  variant = 'outlined' // inferred as string ,
  plus = false,
  rounded = true,
  onClick,
  longPressBind = () => ({}),
})
// after
function ControlButton({
  variant = /** @type{'outlined'} */ ('outlined'),
  plus = false,
  rounded = true,
  onClick,
  longPressBind = () => ({}),
})

위와 같이 작업하면서 딱히 레퍼헌스할 만한 자료들이 많이 없어서 난감했습니다.

혹시 더 자세한 내용이 궁금하시면 댓글로 질문해주세용

더 알아보기 : 

https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html

 

Documentation - JSDoc Reference

What JSDoc does TypeScript-powered JavaScript support?

www.typescriptlang.org

반응형