Type hinting 개요

GitLab 프로젝트의 Frontend 코드베이스는 현재 타입을 필요로 하지 않거나 강제하지 않습니다. 타입 주석을 추가하는 것은 선택사항이며, 현재 JavaScript 코드베이스에서 타입 안전성을 강제하지는 않습니다. 그러나 타입 주석은 코드베이스에 명확성을 추가하는 데 매우 도움이 될 수 있으며 특히 공유 유틸리티 코드에서 유용합니다. 이 문서는 현재 타입 힌팅이 어떻게 작동하는지, 새로운 타입 주석을 추가하는 방법, 그리고 GitLab 프로젝트에서 타입 힌팅을 설정하는 방법을 다루고 있습니다.

JSDoc

JSDoc은 JavaScript 코드에서 특별히 형성된 주석을 사용하여 타입을 문서화하고 설명하는 도구입니다. JSDoc의 타입 어휘는 비교적 제한적이지만 많은 IDE에서 널리 지원됩니다.

예시

함수 설명

함수 타입을 설명하기 위해 @param@returns을 사용합니다:

/**
 * 두 숫자를 더함
 * @param {number} a 첫 번째 숫자
 * @param {number} b 두 번째 숫자
 * @returns {number} 두 숫자의 합
 */
function add(a, b) {
    return a + b;
}
선택적 매개변수

매개변수 주변에 대괄호 []를 사용하여 선택적으로 지정할 수 있습니다. 기본값은 [name=value] 구문을 사용하여 제공할 수 있습니다:

/**
 * 두 숫자를 더함
 * @param {number} value
 * @param {number} [increment=1] 선택적 매개변수
 * @returns {number} 두 숫자의 합
 */
function increment(a, b=1) {
    return a + b;
}
객체 매개변수

객체를 받는 함수는 @param 이름에서 object.field 표기법을 사용하여 타입을 지정할 수 있습니다:

/**
 * 두 숫자를 더함
 * @param {object} config
 * @param {string} config.path 경로
 * @param {string} [config.anchor] 앵커
 * @returns {string}
 */
function createUrl(config) {
    if (config.anchor) {
        return path + '#' + anchor;
    }
    return path;
}

즉시 값이 할당되지 않은 변수의 타입 주석

도구 및 IDE에서 즉시 값이 할당되지 않은 변수의 타입을 추론하는 것은 어려울 수 있습니다. 이러한 변수에 타입을 할당하기 위해 @type 주석을 사용할 수 있습니다:

/** @type {number} */
let value;

더 많은 구문 정보는 JSDoc 공식 웹사이트를 참고하세요.

JSDoc 사용 팁

기본 유형에 대해 소문자 이름 사용

대문자 Boolean과 소문자 boolean 둘 다 허용되지만, 대부분의 경우 기본 유형이 필요한 경우 소문자 버전이 옳은 선택입니다: boolean, number, string, symbol, object.

/**
 * `text`를 번역함.
 * @param {string} text - 번역해야 할 텍스트
 * @returns {string} 번역된 텍스트
 */
const gettext = (text) => locale.gettext(ensureSingleLine(text));

잘 알려진 유형 사용

HTMLDivElement 또는 Intl과 같은 잘 알려진 유형은 사용할 수 있습니다:

/** @type {HTMLDivElement} */
let element;
/**
 * 현재 로캘용 Intl.DateTimeFormat 인스턴스를 생성함.
 * @param {Intl.DateTimeFormatOptions} [formatOptions] - 사용 가능한 옵션은 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat을 참조하세요
 * @returns {Intl.DateTimeFormat}
 */
const createDateTimeFormat = (formatOptions) =>
  Intl.DateTimeFormat(getPreferredLocales(), formatOptions);

import('path/to/module')를 사용하여 기존 타입 정의 가져오기

다음은 즉시 정의되지 않은 Vue Test Utils Wrapper 변수의 타입을 주석 처리하는 방법에 대한 예시입니다:

/** @type {import('helpers/vue_test_utils_helper').ExtendedWrapper} */
let wrapper;
// ...
wrapper = mountExtended(/* ... */);
/** @type {import('@vue/test-utils').Wrapper} */
let wrapper;
// ...
wrapper = shallowMount(/* ... */);

주의: import()기본 JSDoc 구조가 아닙니다 하지만 많은 IDE와 도구에서 인식됩니다. 이 경우, 코드의 명확성과 향상된 개발자 경험을 목표로 합니다.

JSDoc은 제한적입니다

위에서 언급했듯이, JSDoc에는 제한적인 어휘가 있습니다. 그리고 사용 시 타입을 완전히 설명하지 못할 수 있습니다. 그러나 때로는 3rd party 라이브러리의 타입 정의를 사용하여 타입 추론이 우리의 코드에서 작동하도록 할 수 있습니다. 다음은 이러한 방법의 한 예입니다:

- export const mountExtended = (...args) => extendedWrapper(mount(...args));
+ import { compose } from 'lodash/fp';
+ export const mountExtended = compose(extendedWrapper, mount);

여기서 compose 함수의 TypeScript 타입 정의를 사용하여 mountExtended 함수에 유추된 타입 정의를 추가합니다. 이 경우, mountExtended의 매개변수는 mount의 매개변수와 동일한 유형이 될 것입니다. 그리고 반환 유형은 extendedWrapper의 반환 유형과 동일하게 됩니다.

여전히 JSDoc의 구문을 사용하여 함수에 설명을 추가할 수 있습니다. 예를 들어:

/** 컴포넌트를 장착하고 그에 대한 확장된 래퍼를 반환함 */
export const mountExtended = compose(extendedWrapper, mount);

시스템 요구 사항

IDE 및 도구에서 GitLab 코드베이스 및 제3자 패키지의 유형 정의가 올바르게 표시되도록 설정이 필요할 수 있습니다.

별칭

우리의 코드베이스는 많은 별칭을 사용합니다. 예를 들어 import Api from '~/api';app/assets/javascripts/api.js 파일을 가져옵니다. 그러나 IDE는 그 별칭을 알지 못할 수 있으며 따라서 Api의 유형을 알지 못할 수 있습니다. 대부분의 IDE에서 이를 해결하려면 — jsconfig.json 파일을 만들어야 합니다.

GitLab 프로젝트에는 웹팩 구성 및 현재 환경 변수에 기반한 jsconfig.json 파일을 생성하거나 업데이트하는 스크립트가 있습니다. jsconfig.json 파일을 생성하거나 업데이트하려면 — GitLab 프로젝트 루트에서 다음을 실행합니다:

node scripts/frontend/create_jsconfig.js

jsconfig.json은 gitignore 목록에 추가되어 있으므로 GitLab 프로젝트에서 Git 변경을 유발시키지 않습니다. 이는 또한 Git 풀에 포함되지 않으므로 수동으로 생성하거나 업데이트해야 합니다.

제3자 TypeScript 정의

더 많은 라이브러리가 유형 정의에 TypeScript를 사용하는 반면, 일부 라이브러리는 여전히 JSDoc 주석이 달린 유형이나 전혀 유형이 없을 수 있습니다. 이것을 커버하기 위해 TypeScript 커뮤니티는 인기있는 JavaScript 라이브러리에 대한 독립적인 형식 정의를 생성하고 지원하는 DefinitelyTyped 이니셔티브를 시작했습니다. 우리는 이러한 정의를 사용할 수 있으며, 유형 패키지를 명시적으로 설치 (yarn add -D "@types/lodash")하거나 자동 유형 습득 (ATA)라는 기능을 사용하여 사용할 수 있습니다. 이는 일부 언어 서비스에서 사용할 수 있습니다 (예: VS Code의 ATA).

자동 유형 습득 (ATA)은 DefinitelyTyped 목록에서 자동으로 유형 정의를 가져옵니다. 그러나 ATA가 작동하려면 전역으로 설치된 npm이 필요할 수 있습니다. IDE는 npm 실행 파일의 위치를 설정할 수 있는 대체 구성 옵션을 제공할 수 있습니다. 자세한 내용은 IDE 설명서를 참조하십시오.

ATA가 보장되지 않으며 Lodash가 많은 유틸리티 기능의 기반임으로, 우리는 package.jsondevDependencies에 명시적으로 Lodash에 대한 DefinitelyTyped 정의를 추가했습니다. 이를 통해 모든 사람이 lodash 기반 함수에 대한 유형 힌트를 기본 제공으로 받을 수 있습니다.