🌿 TypeScript 5.1μ—μ„œ λ³€κ²½λœ 점은 λ¬΄μ—‡μΌκΉŒμš”?

MISO :-)

🌿 TypeScript 5.1μ—μ„œ λ³€κ²½λœ 점은 λ¬΄μ—‡μΌκΉŒμš”?

2023λ…„ 06μ›” 19일

7λΆ„

0λͺ…μ˜ μ‚¬λžŒμ΄ μ½μ–΄λ΄€μ–΄μš”

πŸ“ TL;DR (3쀄 μš”μ•½)

개인적으둜 TypeScript 5.1μ—μ„œ κ°€μž₯ μ€‘μš”ν•˜κ²Œ μƒκ°ν•˜λŠ” 3κ°€μ§€λŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • React Server Component의 비동기 μ»΄ν¬λ„ŒνŠΈλ₯Ό μœ„ν•˜μ—¬ JSX.ElementType μΆ”κ°€
  • λ°˜ν™˜λ¬Έμ΄ μ—†λŠ” ν•¨μˆ˜μ—μ„œ return νƒ€μž… undefined μž‘μ„± κ°€λŠ₯
  • TypeScript 5.1μ—μ„œ ES2020을 μ§€μ›ν•¨μœΌλ‘œμ¨ Node.js의 μ΅œμ†Œ 버전 λ³€κ²½

✨JSX Element와 JSX νƒœκ·Έ νƒ€μž… 별도 ꡬ뢄 (React Server Components의 ν•œκ³„μ  μˆ˜μ •)

개인적으둜 μƒκ°ν•˜κΈ°μ— 5.1이 μƒκ²¨λ‚œ κ°€μž₯ 큰 μ΄μœ κ°€ μ•„λ‹κΉŒ μ‹ΆμŠ΅λ‹ˆλ‹€. ν˜„μž¬μ˜ React Server ComponentλŠ” νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„  μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.


κ·Έ μ΄μœ λŠ” React Server Componentμ—μ„œ async μ»΄ν¬λ„ŒνŠΈ (비동기 μ»΄ν¬λ„ŒνŠΈ)λ₯Ό λ„μž…ν–ˆκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

const MyAsyncComponent = async () => {
  return <div></div>;
};

const Parent = () => {
  //  ~~~~~~
  // 'MyAsyncComponent'λŠ” JSX ꡬ성 μš”μ†Œλ‘œ μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
  // λ°˜ν™˜ νƒ€μž… 'Promise<Element>'λŠ” μœ νš¨ν•œ JSX μš”μ†Œκ°€ μ•„λ‹™λ‹ˆλ‹€.
  return <MyAsyncComponent />;
};

5.1 버전 μ΄μ „μ—λŠ” 비동기 μ»΄ν¬λ„ŒνŠΈμ— λŒ€ν•΄ ν•˜λ“œμ½”λ”©λœ νƒ€μž…μ„ μ‚¬μš©ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

React에선 Promise νƒ€μž…μ„ λ°˜ν™˜ν•  수 μžˆλŠ” κΈ°λŠ₯을 μ œμ•ˆν–ˆμ§€λ§Œ ν•΄λ‹Ή 문제둜 인해 ν‘œν˜„ν•  수 μ—†μ—ˆμŠ΅λ‹ˆλ‹€.
또, Reactμ—μ„œ μœ νš¨ν•œ μ½”λ“œμΈ string을 λ°˜ν™˜ν•˜λŠ” 것도 μ •μƒμ μœΌλ‘œ μž‘λ™λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

const MyStringComponent = () => {
  return 'Hello world!';
};
const Parent = () => {
  // 'MyStringComponent'λŠ” JSX ꡬ성 μš”μ†Œλ‘œ μ‚¬μš©ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
  // λ°˜ν™˜ νƒ€μž… 'string'λŠ” μœ νš¨ν•œ JSX μš”μ†Œκ°€ μ•„λ‹™λ‹ˆλ‹€.
  return <MyStringComponent />;
};

이제 TypeScriptλŠ” JSX Element κ°€ μœ νš¨ν•œμ§€ κ³„μ‚°ν•˜κΈ° μœ„ν•΄ JSX.ElementType μ΄λΌλŠ” μ „μ—­ νƒ€μž…μ„ μ°Έμ‘°ν•©λ‹ˆλ‹€.

namespace JSX {
    export type ElementType =
        // All the valid lowercase tags
        keyof IntrinsicAttributes
        // Function components
        (props: any) => Element
        // Class components
        new (props: any) => ElementClass;
    export interface IntrinsictAttributes extends /*...*/ {}
    export type Element = /*...*/;
    export type ClassElement = /*...*/;
}

μ΄λŠ” JSXλ₯Ό μ‚¬μš©ν•˜λŠ” ν”„λ ˆμž„μ›Œν¬ (ex: React, Solid, Qwik)에 μœ νš¨ν•œ JSX Element λ₯Ό κ΅¬μ„±ν•˜λŠ” ν•­λͺ©μ— λŒ€ν•΄ 훨씬 더 λ§Žμ€ μ œμ–΄ κΆŒν•œμ„ λΆ€μ—¬ν•˜λ©° JSX 자체λ₯Ό μ‚¬μš©ν•˜λŠ” μƒˆλ‘œμš΄ API의 κ°€λŠ₯성을 μ—΄μ–΄μ€λ‹ˆλ‹€.

βœ¨λ°˜ν™˜λ¬Έμ΄ μ—†λŠ” ν•¨μˆ˜μ— undefined νƒ€μž… μ‚¬μš© κ°€λŠ₯

μ›λž˜ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„  return 없이 ν•¨μˆ˜λ₯Ό λλ‚΄λŠ” 경우 undefined λ₯Ό λ¦¬ν„΄ν•©λ‹ˆλ‹€.

function foo() {
  // 리턴 μ—†μŒ!
}
// x = undefined
let x = foo();

κ·ΈλŸ¬λ‚˜ 이전 λ²„μ „μ˜ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„  λ°˜ν™˜λ¬Έμ΄ μ „ν˜€ 없을 수 μžˆλŠ” μœ μΌν•œ ν•¨μˆ˜λŠ” void 와 any νƒ€μž…μ˜ ν•¨μˆ˜μ˜€μŠ΅λ‹ˆλ‹€. 즉, ν•¨μˆ˜κ°€ undefined λ₯Ό λ°˜ν™˜ν•œλ‹€κ³  λͺ…μ‹œμ μœΌλ‘œ μž‘μ„±ν•˜μ—¬λ„ μ΅œμ†Œν•œ ν•˜λ‚˜μ˜ return 문이 μ‘΄μž¬ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€.

// βœ… OK - f1은 voidλ₯Ό λ°˜ν™˜ν•œλ‹€κ³  μΆ”λ‘ ν•©λ‹ˆλ‹€.
function f1() {
  // no returns
}
// βœ… OK - 'void'λŠ” return 문이 ν•„μš”μ—†μŠ΅λ‹ˆλ‹€.
function f2(): void {
  // no returns
}
// βœ… OK - 'any'λŠ” return 문이 ν•„μš”μ—†μŠ΅λ‹ˆλ‹€.
function f3(): any {
  // no returns
}

// ❌ Error!
// μ„ μ–Έλœ μœ ν˜•μ΄ 'void'도 'any'도 μ•„λ‹Œ ν•¨μˆ˜λŠ” 값을 λ°˜ν™˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.
function f4(): undefined {
  // no returns
}

ν•˜μ§€λ§Œ, 일뢀 APIμ—μ„œ undefined λ₯Ό λ°˜ν™˜ν•œλ‹€κ³  μ˜ˆμƒν•˜λŠ” ν•¨μˆ˜λŠ” λ¬Έμ œκ°€ 생길 수 μžˆμŠ΅λ‹ˆλ‹€.
이것을 ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„  undefined λ₯Ό λͺ…μ‹œμ μœΌλ‘œ λ°˜ν™˜ν•˜κ±°λ‚˜, returnλ¬Έκ³Ό λ°˜ν™˜ νƒ€μž… λͺ…μ‹œλ₯Ό ν•΄μ•Ό ν•©λ‹ˆλ‹€.

declare function takesFunction(f: () => undefined): undefined;
// ❌ Error!
// '() => void' μœ ν˜•μ˜ μΈμˆ˜λŠ” '() => undefined' μœ ν˜•μ˜ λ§€κ°œλ³€μˆ˜μ— ν• λ‹Ήν•  수 μ—†μŠ΅λ‹ˆλ‹€.
takesFunction(() => {
  // no returns
});
// ❌ Error!
// μ„ μ–Έλœ μœ ν˜•μ΄ 'void'도 'any'도 μ•„λ‹Œ ν•¨μˆ˜λŠ” 값을 λ°˜ν™˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.
takesFunction((): undefined => {
  // no returns
});
// ❌ Error!
// '() => void' μœ ν˜•μ˜ μΈμˆ˜λŠ” '() => undefined' μœ ν˜•μ˜ λ§€κ°œλ³€μˆ˜μ— ν• λ‹Ήν•  수 μ—†μŠ΅λ‹ˆλ‹€.
takesFunction(() => {
  return;
});

// βœ… OK
takesFunction(() => {
  return undefined;
});
// βœ… OK
takesFunction((): undefined => {
  return;
});

이 였λ₯˜λŠ” 특히 μ œμ–΄ν•  수 μ—†λŠ” ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ 아쉬움이 λ§Žμ•˜μŠ΅λ‹ˆλ‹€.

undefined 에 λŒ€ν•˜μ—¬ void 둜 μΆ”λ‘ λ˜κ±°λ‚˜ undefined λ°˜ν™˜ ν•¨μˆ˜μ— return 문이 ν•„μš”ν•œμ§€ μ—¬λΆ€λŠ” μ½”λ“œλ₯Ό μ΄ν•΄ν•˜λŠ” 것에 어렀움을 μ£ΌλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.


이 상황을 κ³ λ €ν•˜μ—¬ νƒ€μž…μŠ€ν¬λ¦½νŠΈ 5.1은 μ΄λ ‡κ²Œ λ³€ν™”ν•˜μ˜€μŠ΅λ‹ˆλ‹€.


첫째, νƒ€μž…μŠ€ν¬λ¦½νŠΈ 5.1은 이제 undefined ν•¨μˆ˜μ— λŒ€ν•΄ λ°˜ν™˜λ¬Έμ΄ μ—†λŠ” 것을 ν—ˆμš©ν•©λ‹ˆλ‹€.

// βœ… TypeScript 5.1에선 μ •μƒμ μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€.
function f4(): undefined {
  // 리턴 μ—†μŒ
}
// βœ… TypeScript 5.1에선 μ •μƒμ μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€.
takesFunction((): undefined => {
  // 리턴 μ—†μŒ
});

λ‘˜μ§Έ, ν•¨μˆ˜μ— λ°˜ν™˜λ¬Έμ΄ μ—†κ³  μ •μ˜λ˜μ§€ μ•ŠλŠ” 것을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λŠ” undefined νƒ€μž…μœΌλ‘œ νƒ€μž… 좔둠이 λ©λ‹ˆλ‹€.

// βœ… TypeScript 5.1에선 μ •μƒμ μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€.
takesFunction(function f() {
  //                 ^ 리턴 νƒ€μž…μ€ undefined
  // 리턴 μ—†μŒ
});
// βœ… TypeScript 5.1에선 μ •μƒμ μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€.
takesFunction(function f() {
  //                 ^ 리턴 νƒ€μž…μ€ undefined
  return;
});

사싀 μˆ˜μ •λ˜μ§€ μ•Šμ•„λ„ λ˜λŠ” 건 μ•„λ‹Œκ°€μš”?

void λŠ” μ²˜λ¦¬ν•˜κΈ° κΉŒλ‹€λ‘œμš°λ©° νƒ€μž…μ— 였λ₯˜κ°€ μžˆμ–΄λ„ μž‘λ™μ΄ λ˜λŠ” 문제λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€. 슬쩍 힌트λ₯Ό λ‚¨κΈ°μžλ©΄, νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ void νƒ€μž…μ„ μ‚¬μš©ν•˜λ”λΌλ„ 값을 return ν•  수 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.


Getter, Setter에 κ°’κ³Ό μƒκ΄€μ—†λŠ” νƒ€μž… μ‚¬μš© κ°€λŠ₯

TypeScript 4.3μ—μ„œλŠ” get, set μ ‘κ·Όμž 쌍이 μ„œλ‘œ λ‹€λ₯Έ 두 가지 νƒ€μž…μ„ 지정할 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

interface Serializer {
  set value(v: string | number | boolean);
  get value(): string;
}
declare let box: Serializer;
// 'boolean'도 ν—ˆμš©λ˜μ–΄ μžˆκΈ°μ— 값을 넣을 수 μžˆμŠ΅λ‹ˆλ‹€.
box.value = true;
// 여기에선 'string'으둜 λ‚˜μ˜΅λ‹ˆλ‹€.
console.log(box.value.toUpperCase());

μœ„ μ½”λ“œμ—μ„œ 보이듯이 μ§€κΈˆκΉŒμ§€λŠ” get νƒ€μž…μ΄ set νƒ€μž…μ˜ ν•˜μœ„ νƒ€μž…μ΄μ—¬μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ, getter와 setterκ°€ μ™„μ „νžˆ κ΄€κ³„μ—†λŠ” νƒ€μž…μΈ APIκ°€ μžˆμŠ΅λ‹ˆλ‹€.


예λ₯Ό λ“€μ–΄, κ°€μž₯ 일반적인 μ˜ˆμ‹œ CSSStyleRule APIκ°€ μžˆμŠ΅λ‹ˆλ‹€.

style setterλŠ” λ¬Έμžμ—΄ νƒ€μž…μ„ λ°›μ•„ 객체둜 λ³€ν™˜ν•œ ν›„ Element에 ν• λ‹Ήν•˜κ³ , style getterλŠ” CSSStyleDeclaration 객체λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.


ν•˜μ§€λ§Œ μ΄μ „μ˜ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„  getter, setterκ°€ κ΄€λ ¨μ—†λŠ” νƒ€μž…μ„ μ •ν•  수 μ—†μ—ˆκΈ°μ— μ•„λž˜μ™€ 같이 μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄ μ—λŸ¬κ°€ λ°œμƒν•  κ²ƒμž…λ‹ˆλ‹€.

declare const el: HTMLDivElement;

// Before 5.1: Cannot assign to 'style' because it is a read-only property.ts
// style μ†μ„±μ˜ μ“°κΈ° νƒ€μž…μ„ 별도 지정이 λΆˆκ°€λŠ₯ν•˜μ—¬, readonly νƒ€μž…μœΌλ‘œ λ˜μ–΄μžˆμŒ.
el.style = 'color: red;';

ν•˜μ§€λ§Œ 이제 κ·œμΉ™μ΄ μ™„ν™”λ˜μ–΄ μ™„μ „νžˆ λ‹€λ₯Έ νƒ€μž…μ˜ getter와 setterλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
아직 λ‚΄μž₯ μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ΄ μˆ˜μ •λ˜μ§„ μ•Šμ•˜μ§€λ§Œ μˆ˜μ •μ΄ λœλ‹€λ©΄ 이런 μ‹μ˜ μ½”λ“œλ„ κ°€λŠ₯ν•©λ‹ˆλ‹€.

declare const el: HTMLDivElement;

// After 5.1: μœ„ CSSStyleRule의 κ΅¬ν˜„λŒ€λ‘œ ν—ˆμš©λ¨.
el.style = 'background: red;';

JSX 속성에 λ„€μž„μŠ€νŽ˜μ΄μŠ€ 이용 κ°€λŠ₯

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” 이제 JSXλ₯Ό μ‚¬μš©ν•  λ•Œ λ„€μž„μŠ€νŽ˜μ΄μŠ€ 속성 이름을 μ§€μ›ν•©λ‹ˆλ‹€.


JSXμ—μ„œ HTML이 μ•„λ‹Œ XMLμ—μ„œ λ‚˜μ˜¨ λ„€μž„μŠ€νŽ˜μ΄μŠ€ 속성을 μ§€μ›ν•˜λŠ” 것이 λ†€λžκ²Œ λŠκ»΄μ§€μ‹€ 수 μžˆμŠ΅λ‹ˆλ‹€.
λ‹€λ§Œ ν₯미둜운 점은 JSXκ°€ HTML을 μƒμ„±ν•˜λŠ” 데에 μ‚¬μš©λ˜μ§€λ§Œ XMLμ—μ„œ μ˜κ°μ„ λ°›μ•˜λ‹€λŠ” μ μž…λ‹ˆλ‹€.


그렇기에 JSX 사양이 λ„€μž„μŠ€νŽ˜μ΄μŠ€ μ–΄νŠΈλ¦¬λ·°νŠΈλ₯Ό ν—ˆμš©ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.
ν•˜μ§€λ§Œ μ§€κΈˆκΉŒμ§€ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—λŠ” 이에 λŒ€ν•œ μ •μ˜κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.


λ„€μž„μŠ€νŽ˜μ΄μŠ€ νƒœκ·Έ 이름은 μ΄λ¦„μ˜ 첫 번째 μ„Έκ·Έλ¨ΌνŠΈκ°€ μ†Œλ¬Έμž 이름일 λ•Œ JSX.IntrinsicAttributes 와 μœ μ‚¬ν•œ λ°©μ‹μœΌλ‘œ μ‘°νšŒλ©λ‹ˆλ‹€.

// 일뢀 λΌμ΄λΈŒλŸ¬λ¦¬λ‚˜ ν•΄λ‹Ή 라이브러리의 ν™•μž₯μ—μ„œ μ΄λ ‡κ²Œ μ„ μ–Έν•˜λ©΄
namespace JSX {
  interface IntrinsicElements {
    ['a:b']: { prop: string };
  }
}
// μ½”λ“œμ—μ„œ μ΄λ ‡κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
let x = <a:b prop="hello!" />;

λ„€μž„μŠ€νŽ˜μ΄μŠ€ 속성은 μƒμœ„-ν•˜μœ„ 속성 κ·Έλ£Ήκ³Ό 속성 이름 μΆ©λŒμ„ λ°©μ§€ν•˜λŠ” 데에 μœ μš©ν•˜κ²Œ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€.

✨ES2020 μ΅œμ†Œ λŸ°νƒ€μž„ λ³€κ²½

νƒ€μž…μŠ€ν¬λ¦½νŠΈ 5.1은 ECMAScript 2020에 λ„μž…λœ μžλ°”μŠ€ν¬λ¦½νŠΈ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.


λ”°λΌμ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μƒλ‹Ήνžˆ 높은 λ²„μ „μ˜ λŸ°νƒ€μž„μ—μ„œ μ‹€ν–‰λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. μ΄μ œλŠ” Node.js 14.17 버전 μ΄μƒμ—μ„œλ§Œ 싀행됨을 μ˜λ―Έν•©λ‹ˆλ‹€.


Node 10μ΄λ‚˜ 12 같은 λ²„μ „μ˜ Node.jsμ—μ„œ νƒ€μž…μŠ€ν¬λ¦½νŠΈ 5.1을 μ‹€ν–‰ν•˜λ €κ³  ν•˜λ©΄ tsc.js λ˜λŠ” tsserver.js μ—μ„œ λ‹€μŒκ³Ό 같은 였λ₯˜κ°€ ν‘œμ‹œλ  수 μžˆμŠ΅λ‹ˆλ‹€.

node_modules/typescript/lib/tsserver.js:2406
  for (let i = startIndex ?? 0; i < array.length; i++) {
                           ^

SyntaxError: Unexpected token '?'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

또 νƒ€μž…μŠ€ν¬λ¦½νŠΈλ₯Ό μ„€μΉ˜ν•˜λ €κ³  ν•˜λ©΄ npmμ—μ„œ λ‹€μŒκ³Ό 같은 였λ₯˜ λ©”μ„Έμ§€λ‘œ ν‘œμ‹œλ©λ‹ˆλ‹€.

npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'typescript@5.1.1-rc',
npm WARN EBADENGINE   required: { node: '>=14.17' },
npm WARN EBADENGINE   current: { node: 'v12.22.12', npm: '8.19.2' }
npm WARN EBADENGINE }

Yarnμ—μ„œλŠ” μ΄λ ‡κ²Œ ν‘œμ‹œλ©λ‹ˆλ‹€.

error typescript@5.1.1-rc: The engine "node" is incompatible with this module. Expected version ">=14.17". Got "12.22.12"
error Found incompatible module.

μ΅œμ ν™” μž‘μ—…

더 λΉ λ₯Έ λ¦¬ν„°λŸ΄ νƒ€μž…

λ¦¬ν„°λŸ΄ νƒ€μž…μ€ λ³΅μž‘ν•˜κ³  λ¦¬μ†ŒμŠ€λ₯Ό 많이 μ‚¬μš©ν•˜λŠ” ꡬ쑰둜 λ˜μ–΄μžˆμ—ˆμŠ΅λ‹ˆλ‹€.

μœ„μ™€ 같이 νƒ€μž…μ„ μž‘μ„±ν•˜λ©΄ νƒ€μž… 검사에 μ•½ 50μ΄ˆκ°€ κ±Έλ ΈμœΌλ‚˜ ν˜„μž¬λŠ” λ³€κ²½λ˜μ–΄ 0.4초둜 λ‹¨μΆ•λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

λ‹€λ₯Έ 변경점도 μ•Œκ³ μ‹Άμ–΄μš”! πŸ€“

@param νƒœκ·Έ μžλ™μ™„μ„± 지원

νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” 이제 νƒ€μž…μŠ€ν¬λ¦½νŠΈ, μžλ°”μŠ€ν¬λ¦½νŠΈ 파일 λͺ¨λ‘μ—μ„œ @param νƒœκ·Έλ₯Ό μž…λ ₯ν•  λ•Œ μ½”λ“œ μžλ™μ™„μ„±μ„ μ œκ³΅ν•©λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ μ½”λ“œλ₯Ό λ¬Έμ„œν™”ν•˜κ±°λ‚˜ μžλ°”μŠ€ν¬λ¦½νŠΈμ—μ„œ JSDoc νƒ€μž…μ„ μΆ”κ°€ν•  λ•Œ 일뢀 타이핑 및 ν…μŠ€νŠΈ 이동을 μ€„μ΄λŠ” 데 도움이 될 수 μžˆμŠ΅λ‹ˆλ‹€.


λ‹¨μˆœν•œ μžλ™μ™„μ„±μ΄μ§€λ§Œ 이미 JSDoc에 μ •μ˜λ˜μ–΄ μžˆλŠ” νŒŒλΌλ―Έν„° λͺ©λ‘μ„ 기반으둜 힌트λ₯Ό 쀄여주기에 μ’‹μŠ΅λ‹ˆλ‹€.

typeRoots λ₯Ό μ΄μš©ν•˜μ—¬ 적용된 νŒ¨ν‚€μ§€ 확인

νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ μ§€μ •λœ λͺ¨λ“ˆ 쑰회 μ „λž΅μ„ μ‚¬μš©ν•˜μ—¬ 경둜λ₯Ό 확인할 수 μ—†λŠ” 경우 μ΄μ œλŠ” μ§€μ •λœ typeRoots 의 μƒλŒ€μ μΈ νŒ¨ν‚€μ§€λ₯Ό ν™•μΈν•©λ‹ˆλ‹€.

μ„ μ–Έλœ νƒ€μž…μ„ κΈ°μ‘΄ νŒŒμΌμ— μ μš©μ‹œν‚¬ 수 μžˆλŠ” VSCode κΈ°λŠ₯ 제곡

export ꡬ문을 μƒˆ 파일둜 μ΄λ™ν•˜λŠ” 것 외에도 νƒ€μž…μŠ€ν¬λ¦½νŠΈλŠ” μ„ μ–Έ ꡬ문을 κΈ°μ‘΄ 파일둜 μ΄λ™ν•˜κΈ° μœ„ν•œ 미리보기 κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.


μ΅œμ‹  λ²„μ „μ˜ VSCodeμ—μ„œ 이 κΈ°λŠ₯을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

참고자료