π 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μμ μ΄ κΈ°λ₯μ μ¬μ©ν μ μμ΅λλ€.
μ°Έκ³ μλ£
- https://www.totaltypescript.com/typescript-5-1-beta-breakdown
- https://tomaszs2.medium.com/typescript-5-1-beta-is-relaxed-friendly-and-fast-9dd0e95e5e68
- https://opnay.com/p/fe0fd843-eed0-4f39-a0b0-796eb542290d
- https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md
- https://itchallenger.tistory.com/760
- https://vived.io/new-hook-is-coming-to-react-frontend-weekly-vol-109/