라이브러리, 프레임워크•2026.03.25
npm install -D typescriptimport ... assert {...}와 같은 임포트 단언(Import Assertion) 구문의 지원 중단(Deprecation) 범위를 import(..., { assert: {...}})와 같은 import() 호출까지 확장했습니다.this를 사용하지 않는 함수에서의 문맥 의존성 완화declare function callIt<T>(obj: { produce: (x: number) => T, consume: (y: T) => void,}): void;// 문제없이 작동합니다.callIt({ produce: (x: number) => x * 2, consume: y => y.toFixed(),});// 속성의 순서가 바뀌어도 문제없이 작동합니다.callIt({ consume: y => y.toFixed(), produce: (x: number) => x * 2,});produce 함수에서 추론된 T를 바탕으로 consume 함수의 y 타입을 추론할 수 있습니다. 하지만 이 함수들이 화살표 함수 구문 대신 메서드 구문으로 작성되었다면 어떨까요?declare function callIt<T>(obj: { produce: (x: number) => T, consume: (y: T) => void,}): void;// 잘 작동하며, `x`는 number로 추론됩니다.callIt({ produce(x: number) { return x * 2; }, consume(y) { return y.toFixed(); },});callIt({ consume(y) { return y.toFixed(); }, // ~ // 오류: 'y'의 타입이 'unknown'입니다. produce(x: number) { return x * 2; },});callIt의 두 번째 호출에서는 오류가 발생합니다. TypeScript가 consume 메서드에서 y의 타입을 추론하지 못하기 때문입니다. 이는 TypeScript가 T의 후보를 찾을 때, 매개변수에 명시적 타입이 없는 함수를 먼저 건너뛰기 때문에 발생합니다. 특정 함수들은 올바른 체크를 위해 추론된 T의 타입이 필요할 수 있기 때문인데, 우리의 경우 consume 함수를 분석하기 위해 T의 타입을 알아야 합니다.function callFunc<T>(callback: (x: T) => void, value: T) { return callback(value);}callFunc(x => x.toFixed(), 42);// ^// 여기서 `x`의 타입을 알아내야 하지만,// 콜백을 체크하기 위해 `T`의 타입도 알아내야 합니다.T에 대한 추론 중에 콜백을 건너뛰지만, 두 번째 인자인 42를 보고 T가 number임을 추론합니다. 그 후 다시 콜백을 체크하러 돌아오면 (x: number) => void라는 문맥적 타입을 갖게 되어 x 또한 number로 추론할 수 있게 됩니다.// 화살표 구문 - 오류 없음.callIt({ consume: y => y.toFixed(), produce: (x: number) => x * 2,});// 메서드 구문 - 오류 발생!callIt({ consume(y) { return y.toFixed(); }, // ~ // 오류: 'y'의 타입이 'unknown'입니다. produce(x: number) { return x * 2; },});produce에 명시적 타입의 x 매개변수를 가진 함수가 할당되었습니다. 동일하게 체크되어야 하지 않을까요?this 매개변수를 갖지만, 화살표 함수는 그렇지 않습니다. this를 사용하면 T의 타입을 "끌어당겨야" 할 수도 있습니다. 예를 들어, 포함하는 객체 리터럴의 타입을 아는 것이 T를 사용하는 consume의 타입을 요구할 수도 있기 때문입니다.this를 사용하지 않고 있습니다! 물론 함수가 런타임에 this 값을 가질 수는 있지만, 전혀 사용되지 않습니다!this가 실제로 사용되지 않는다면, 해당 함수는 문맥 의존적인 것으로 간주되지 않습니다. 즉, 이러한 함수들은 타입 추론 시 더 높은 우선순위를 갖게 되며, 위의 모든 예시가 이제 정상적으로 작동합니다!#/로 시작하는 서브패스 임포트imports라는 필드를 통해 패키지 내부 모듈에 대한 별칭(Alias)을 생성할 수 있게 해줍니다.{ "name": "my-package", "type": "module", "imports": { "#root/*": "./dist/*" }}my-package 내부의 모듈들은 다음과 같은 상대 경로 대신import * as utils from "../../utils.js";#root/로 시작하는 경로를 사용하여 임포트할 수 있습니다.import * as utils from "#root/utils.js";# 뒤에 항상 무언가를 써야 했다는 점입니다. 위 예시에서는 root를 사용했지만, ./dist/ 외에 매핑할 다른 디렉토리가 없는 경우에는 다소 불필요하게 느껴집니다.@/를 접두사로 사용하는 것이었습니다. 불행히도 서브패스 임포트는 #/로 시작할 수 없었기에, 이를 프로젝트에 도입하려는 개발자들에게 많은 혼란을 주었습니다.#/로 시작하는 서브패스 임포트 지원이 추가되었습니다. 이제 패키지들은 추가적인 세그먼트 없이 간단한 #/ 접두사를 서브패스 임포트에 사용할 수 있습니다.{ "name": "my-package", "type": "module", "imports": { "#/*": "./dist/*" }}--moduleResolution 설정의 nodenext 및 bundler 옵션에서 이를 지원합니다.--moduleResolution bundler와 --module commonjs 조합--moduleResolution bundler 설정은 이전에는 --module esnext 또는 --module preserve와만 함께 사용할 수 있었습니다. 하지만 --moduleResolution node(일명 --moduleResolution node10)가 지원 중단됨에 따라, 이 새로운 조합이 많은 프로젝트에서 가장 적합한 업그레이드 경로가 되는 경우가 많습니다.--module preserve 및 --moduleResolution bundler--module nodenext--stableTypeOrdering 플래그// 입력: some-file.tsexport function foo(condition: boolean) { return condition ? 100 : 500;}// 출력: some-file.d.tsexport declare function foo(condition: boolean): 100 | 500;// ^^^^^^^^^// 유니온의 순서에 주목하세요: 100 다음 500.foo 위에 관련 없는 const를 추가하면 선언 파일 생성이 변경됩니다.// 입력: some-file.tsconst x = 500;export function foo(condition: boolean) { return condition ? 100 : 500;}// 출력: some-file.d.tsexport declare function foo(condition: boolean): 500 | 100;// ^^^^^^^^^// 순서가 바뀐 것에 주목하세요.const x 선언을 분석할 때 리터럴 타입 500이 먼저 처리되어 100보다 낮은 타입 ID를 갖게 되기 때문입니다. 매우 드문 경우지만, 이러한 순서 변경으로 인해 프로그램 처리 순서에 따라 오류가 나타나거나 사라질 수도 있습니다. 하지만 일반적으로는 생성된 선언 파일이나 에디터에서 타입이 표시되는 방식에서 주로 차이를 느끼게 됩니다.100 | 500을 출력하여 순서 불안정성을 완전히 제거합니다.--stableTypeOrdering 플래그를 지정할 수 있습니다. 이 플래그는 6.0의 타입 정렬 동작을 7.0과 일치시켜 두 코드베이스 간의 차이를 줄여줍니다. 다만, 이 플래그는 타입 체크 속도를 상당히 늦출 수 있으므로(코드베이스에 따라 최대 25%) 항상 사용하는 것은 권장하지 않습니다.--stableTypeOrdering을 사용할 때 타입 오류가 발생한다면, 이는 대개 추론의 차이 때문입니다. --stableTypeOrdering이 없었을 때의 이전 추론은 프로그램의 현재 타입 순서에 기반하여 우연히 작동했던 것입니다. 이를 해결하려면 어딘가에 명시적인 타입을 제공하는 것이 좋습니다. 주로 타입 인자를 제공하거나- someFunctionCall(/*...*/);+ someFunctionCall<SomeExplicitType>(/*...*/);- const someVariable = { /*... 복잡한 객체 ...*/ };+ const someVariable: SomeExplicitType = { /*... 복잡한 객체 ...*/ };someFunctionCall(someVariable);target 및 lib을 위한 es2025 옵션target과 lib 모두에 대해 es2025 옵션 지원을 추가했습니다. ES2025에 새로운 JavaScript 언어 기능은 없지만, 이 새로운 타겟은 내장 API(예: RegExp.escape)를 위한 새로운 타입을 추가하고, esnext에 있던 몇 가지 선언을 es2025로 이동시킵니다(예: Promise.try, Iterator 메서드, Set 메서드). 새로운 타겟을 활성화하는 작업은 Kenta Moriuchi의 기여로 이루어졌습니다.Temporal을 위한 새로운 타입--target esnext 또는 "lib": ["esnext"](또는 더 세분화된 esnext.temporal)를 통해 오늘 바로 TypeScript 코드에서 사용할 수 있습니다.let yesterday = Temporal.Now.instant().subtract({ hours: 24,});let tomorrow = Temporal.Now.instant().add({ hours: 24,});console.log(`Yesterday: ${yesterday}`);console.log(`Tomorrow: ${tomorrow}`);getOrInsert)를 위한 새로운 타입Map을 사용할 때 흔히 쓰이는 패턴은 키가 존재하는지 확인하고, 없으면 기본값을 설정한 뒤 가져오는 것입니다.function processOptions(compilerOptions: Map<string, unknown>) { let strictValue: unknown; if (compilerOptions.has("strict")) { strictValue = compilerOptions.get("strict"); } else { strictValue = true; compilerOptions.set("strict", strictValue); } // ...}getOrInsertgetOrInsertComputedesnext 라이브러리에 추가되어 TypeScript 6.0에서 즉시 사용할 수 있습니다.getOrInsert를 사용하면 위의 코드를 다음과 같이 바꿀 수 있습니다.function processOptions(compilerOptions: Map<string, unknown>) { let strictValue = compilerOptions.getOrInsert("strict", true); // ...}getOrInsertComputed도 비슷하게 작동하지만, 기본값을 계산하는 비용이 많이 드는 경우(예: 많은 계산, 할당 또는 긴 동기 I/O가 필요한 경우)를 위한 것입니다. 대신 키가 없을 때만 호출될 콜백을 인자로 받습니다.someMap.getOrInsertComputed("someKey", () => { return computeSomeExpensiveValue(/*...*/);});someMap.getOrInsertComputed(someKey, computeSomeExpensiveDefaultValue);function computeSomeExpensiveValue(key: string) { // ...}RegExp.escape*, +, ?, (, ) 등과 같은 특수 정규 표현식 문자를 이스케이프(Escape)하는 것이 중요합니다. RegExp Escaping ECMAScript 제안이 4단계에 도달하여 이를 대신 처리해 주는 새로운 RegExp.escape 함수가 도입되었습니다.function matchWholeWord(word: string, text: string) { const escapedWord = RegExp.escape(word); const regex = new RegExp(`\\b${escapedWord}\\b`, "g"); return text.match(regex);}RegExp.escape는 es2025 라이브러리에서 사용할 수 있으므로, 오늘 바로 TypeScript 6.0에서 사용할 수 있습니다.dom 라이브러리에 dom.iterable 및 dom.asynciterable 포함lib 옵션을 사용하면 대상 런타임이 가진 전역 선언을 지정할 수 있습니다. 웹 환경(즉, DOM API를 구현하는 브라우저)을 나타내기 위해 dom 옵션을 사용합니다. 이전에는 Iterable 및 AsyncIterable을 지원하지 않는 환경을 위해 DOM API가 dom.iterable 및 dom.asynciterable로 부분적으로 분리되어 있었습니다. 이로 인해 NodeList나 HTMLCollection 같은 DOM 컬렉션에서 반복 메서드를 사용하려면 명시적으로 dom.iterable을 추가해야 했습니다.lib.dom.iterable.d.ts 및 lib.dom.asynciterable.d.ts의 내용이 lib.dom.d.ts에 완전히 포함됩니다. 설정 파일의 "lib" 배열에서 여전히 dom.iterable과 dom.asynciterable을 참조할 수 있지만, 이제는 빈 파일일 뿐입니다.// TypeScript 6.0 이전에는 "lib": ["dom", "dom.iterable"]이 필요했습니다.// 이제는 "lib": ["dom"]만으로 작동합니다.for (const element of document.querySelectorAll("div")) { console.log(element.textContent);}dom과 dom.iterable을 모두 포함하고 있었다면 이제 dom으로 단순화할 수 있습니다.tsconfig.json은 설정 메커니즘으로서 거의 보편화되었습니다."ignoreDeprecations": "6.0"을 설정하여 이러한 지원 중단 사항을 무시할 수 있습니다. 하지만 TypeScript 7.0은 이러한 지원 중단된 옵션들을 지원하지 않을 것임에 유의하세요.ts5to6 도구는 코드베이스 전반에 걸쳐 baseUrl과 rootDir을 자동으로 조정할 수 있습니다."types" 배열을 설정하세요. 일반적으로 "types": ["node"]입니다."types": ["*"]를 사용하면 5.9의 동작으로 복구되지만, 빌드 성능과 예측 가능성을 높이기 위해 명시적인 배열을 사용하는 것을 권장합니다.rootDir이 추론되는 것에 의존했다면 "rootDir": "./src"를 설정하세요../dist/index.js 대신 ./dist/src/index.js에 생성된다면 대개 이 문제입니다.strict가 이제 기본적으로 true입니다: 더 엄격한 타이핑에 대한 요구가 계속 커지고 있으며, 대부분의 새로운 프로젝트가 strict 모드를 활성화하기를 원한다는 것을 확인했습니다. 이미 "strict": true를 사용 중이었다면 변경 사항은 없습니다. 이전 기본값인 false에 의존하고 있었다면 tsconfig.json에 명시적으로 "strict": false를 설정해야 합니다.module의 기본값이 esnext가 됩니다: 마찬가지로 ESM이 이제 지배적인 모듈 형식이 되었음을 인정하여 새로운 기본 module 값은 esnext입니다.target의 기본값이 현재 연도의 ES 버전이 됩니다: 새로운 기본 target은 지원되는 가장 최신 ECMAScript 스펙 버전입니다(사실상 유동적인 타겟). 현재 이 타겟은 es2025입니다. 이는 대부분의 개발자가 에버그린 런타임에 배포하며 이전 ECMAScript 버전으로 트랜스파일할 필요가 없다는 현실을 반영합니다.noUncheckedSideEffectImports가 이제 기본적으로 true입니다: 이는 부수 효과 전용(Side-effect-only) 임포트의 오타로 인한 문제를 잡는 데 도움이 됩니다.libReplacement가 이제 기본적으로 false입니다: 이 플래그는 이전에 실행할 때마다 많은 수의 모듈 해제 실패를 유발했으며, 이는 --watch 및 에디터 시나리오에서 감시해야 할 위치의 수를 증가시켰습니다. 새로운 프로젝트에서 libReplacement는 다른 명시적 설정이 있기 전까지는 아무 작업도 하지 않으므로, 기본 성능 향상을 위해 이를 기본적으로 끄는 것이 합리적입니다.tsconfig.json에 이전 값을 명시적으로 지정할 수 있습니다.rootDir의 기본값이 .으로 변경rootDir은 출력 디렉토리에 대한 출력 파일의 디렉토리 구조를 제어합니다. 이전에는 rootDir을 지정하지 않으면 선언 파일이 아닌 모든 입력 파일의 공통 디렉토리를 기반으로 추론되었습니다. 하지만 이는 프로젝트를 로드하고 파싱해 보기 전까지는 파일이 프로젝트에 속하는지 알 수 없음을 의미했습니다. 또한 TypeScript가 프로그램의 모든 파일 경로를 분석하여 공통 소스 디렉토리를 추론하는 데 더 많은 시간을 소비해야 함을 의미했습니다.rootDir은 항상 tsconfig.json 파일이 포함된 디렉토리가 됩니다. rootDir은 tsconfig.json 파일 없이 커맨드 라인에서 tsc를 사용할 때만 추론됩니다.tsconfig.json 디렉토리보다 깊은 단계에 있고 TypeScript가 소스 파일의 공통 루트 디렉토리를 추론하는 것에 의존하고 있었다면, 명시적으로 rootDir을 설정해야 합니다. { "compilerOptions": { // ... "rootDir": "./src" }, "include": ["./src"] }tsconfig.json이 포함된 디렉토리 외부의 파일을 참조하는 경우, 해당 파일들을 포함하도록 rootDir을 조정해야 합니다. { "compilerOptions": { // ... "rootDir": "../src" }, "include": ["../src/**/*.tests.ts"] }types의 기본값이 []로 변경tsconfig.json에서 compilerOptions의 types 필드는 컴파일 중에 전역 스코프에 포함될 패키지 이름 목록을 지정합니다. 일반적으로 node_modules의 패키지들은 소스 코드의 임포트를 통해 자동으로 포함되지만, 편의를 위해 TypeScript는 기본적으로 node_modules/@types의 모든 패키지를 포함했습니다. 덕분에 직접 임포트하지 않고도 @types/node의 process나 "fs" 모듈, 또는 @types/jest의 describe와 it 같은 전역 선언을 사용할 수 있었습니다.types 값은 " node_modules/@types에 있는 모든 것을 열거하라"는 것이 기본값이었습니다. 이는 매우 비용이 많이 들 수 있는데, 오늘날 일반적인 저장소 설정은 특히 평탄화된 node_modules를 가진 멀티 프로젝트 워크스페이스에서 수백 개의 @types 패키지를 전이적으로 끌어올 수 있기 때문입니다. 현대적인 프로젝트는 거의 항상 @types/node, @types/jest 또는 전역에 영향을 미치는 소수의 공통 패키지만 필요로 합니다.types 값은 [](빈 배열)이 됩니다. 이 변경은 프로젝트가 빌드 시 불필요한 수백, 수천 개의 선언 파일을 의도치 않게 끌어오는 것을 방지합니다. 우리가 살펴본 많은 프로젝트에서 types를 적절히 설정하는 것만으로 빌드 시간이 20~50% 개선되었습니다."types": ["node"] 또는 몇 가지 다른 항목을 추가해야 할 것입니다. { "compilerOptions": { // 필요한 @types 패키지를 명시적으로 나열하세요. "types": ["node", "jest"] } }* 항목을 지정하여 이전의 열거 동작을 다시 활성화할 수도 있습니다. { "compilerOptions": { // 모든 타입을 로드합니다 - TypeScript 5.9 이전의 기본값입니다. "types": ["*"] } }Cannot find module '...' or its corresponding type declarations.Cannot find name 'fs'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig....types 필드에 항목을 추가해야 할 가능성이 높습니다.target: es5target: es5 옵션은 지원 중단됩니다. target: es5를 사용 중이었다면 최신 타겟으로 마이그레이션하거나 외부 컴파일러를 사용해야 합니다. 여전히 ES5 출력이 필요하다면 외부 컴파일러를 사용하여 TypeScript 소스를 직접 컴파일하거나 TypeScript의 출력을 후처리하는 것을 권장합니다.--downlevelIteration--downlevelIteration은 ES5 출력에만 영향을 미치며, --target es5가 지원 중단됨에 따라 --downlevelIteration은 더 이상 목적이 없습니다.--target es2015와 함께 --downlevelIteration false를 사용해도 아무런 효과가 없음에도 오류가 발생하지 않았습니다. TypeScript 6.0에서는 --downlevelIteration을 설정하는 것만으로도 지원 중단 오류가 발생합니다.--moduleResolution node (일명 --moduleResolution node10)--moduleResolution node는 Node.js 10의 동작을 가장 정확하게 반영하는 특정 버전의 Node.js 모듈 해제 알고리즘을 인코딩한 것입니다. 불행히도 이 타겟(및 그 이름)은 그 이후에 발생한 Node.js 해제 알고리즘의 많은 업데이트를 무시하며, 더 이상 현대 Node.js 버전의 동작을 잘 대변하지 못합니다.--moduleResolution node(정확히는 --moduleResolution node10)는 지원 중단됩니다. --moduleResolution node를 사용하던 사용자들은 Node.js를 직접 타겟팅하는 경우 --moduleResolution nodenext로, 번들러나 Bun을 사용하는 경우 --moduleResolution bundler로 마이그레이션해야 합니다.module의 amd, umd, systemjs 값--module amd--module umd--module systemjs--module noneamd-module 지시어에 대한 지원 중단을 의미하며, 해당 지시어는 더 이상 아무런 효과가 없습니다.--baseUrlbaseUrl 옵션은 주로 paths와 함께 사용되며, 일반적으로 paths의 모든 값에 대한 접두사로 사용됩니다. 불행히도 baseUrl은 모듈 해제를 위한 조회 루트(Look-up root)로도 간주됩니다.tsconfig.json이 있고{ "compilerOptions": { // ... "baseUrl": "./src", "paths": { "@app/*": ["app/*"], "@lib/*": ["lib/*"] } }}import * as someModule from "someModule.js";@app/ 및 @lib/로 시작하는 모듈에 대해서만 매핑을 추가하려 했음에도 불구하고, TypeScript는 이를 src/someModule.js로 해제할 가능성이 높습니다.baseUrl 지정을 요구하지 않았으며, 실제로 baseUrl을 사용하는 대부분의 프로젝트는 이를 paths 항목의 접두사로만 사용합니다. TypeScript 6.0에서 baseUrl은 지원 중단되며 더 이상 모듈 해제를 위한 조회 루트로 간주되지 않습니다.baseUrl을 경로 매핑 항목의 접두사로 사용했던 개발자들은 단순히 baseUrl을 제거하고 paths 항목에 접두사를 추가하면 됩니다. { "compilerOptions": { // ...- "baseUrl": "./src", "paths": {- "@app/*": ["app/*"],- "@lib/*": ["lib/*"]+ "@app/*": ["./src/app/*"],+ "@lib/*": ["./src/lib/*"] } } }baseUrl을 조회 루트로 사용했던 개발자들은 이전 동작을 유지하기 위해 명시적인 경로 매핑을 추가할 수 있습니다.{ "compilerOptions": { // ... "paths": { // baseUrl을 대체하는 새로운 포괄적 매핑: "*": ["./src/*"], // 이제 다른 모든 경로에 명시적인 공통 접두사가 붙습니다: "@app/*": ["./src/app/*"], "@lib/*": ["./src/lib/*"], } }}baseUrl을 제거하고 paths 항목에 적절한 접두사를 추가하는 것을 권장합니다.--moduleResolution classicmoduleResolution: classic 설정이 제거되었습니다. classic 해제 전략은 TypeScript의 초기 모듈 해제 알고리즘으로, Node.js의 해제 알고리즘이 사실상의 표준이 되기 전의 것입니다. 오늘날 모든 실질적인 사용 사례는 nodenext 또는 bundler로 충족됩니다. classic을 사용 중이었다면 이러한 현대적인 해제 전략 중 하나로 마이그레이션하세요.--esModuleInterop false 및 --allowSyntheticDefaultImports falsefalse로 설정할 수 없습니다.esModuleInteropallowSyntheticDefaultImportsesModuleInterop과 allowSyntheticDefaultImports는 원래 기존 프로젝트의 파손을 피하기 위해 선택 사항(Opt-in)으로 도입되었습니다. 그러나 이들이 활성화하는 동작은 수년 동안 권장되는 기본값이었습니다. 이를 false로 설정하면 ESM에서 CommonJS 모듈을 소비할 때 미묘한 런타임 문제가 발생하는 경우가 많았습니다. TypeScript 6.0에서는 더 안전한 상호 운용(Interop) 동작이 항상 활성화됩니다.// 이전 (esModuleInterop: false 인 경우)import * as express from "express";// 이후 (esModuleInterop이 항상 활성화된 경우)import express from "express";--alwaysStrict falsealwaysStrict 플래그는 "use strict"; 지시어의 추론 및 출력을 의미합니다. TypeScript 6.0에서 모든 코드는 JavaScript 엄격 모드(Strict mode)에 있는 것으로 간주됩니다. 이는 예약어 주변의 구문적 특이 케이스에 주로 영향을 미치는 JS 시맨틱 세트입니다. await, static, private, public과 같은 예약어를 일반 식별자로 사용하는 "슬로피 모드(Sloppy mode)" 코드가 있다면 이름을 변경해야 합니다. 비엄격 모드 코드에서 this의 의미와 관련된 미묘한 시맨틱에 의존했다면 코드 조정이 필요할 수도 있습니다.outFile--outFile 옵션이 TypeScript 6.0에서 제거되었습니다. 이 옵션은 원래 여러 입력 파일을 하나의 출력 파일로 결합하기 위해 설계되었습니다. 그러나 Webpack, Rollup, esbuild, Vite, Parcel 등과 같은 외부 번들러들이 이제 이 작업을 훨씬 빠르고 더 나은 설정 기능으로 수행합니다. 이 옵션을 제거함으로써 구현을 단순화하고 TypeScript가 가장 잘하는 일인 타입 체크와 선언 파일 생성에 집중할 수 있게 되었습니다. 현재 --outFile을 사용 중이라면 외부 번들러로 마이그레이션해야 합니다. 대부분의 현대적인 번들러는 기본적으로 뛰어난 TypeScript 지원을 제공합니다.module 구문module 키워드를 사용했습니다.// ❌ 지원 중단된 구문 - 이제 오류 발생module Foo { export const bar = 10;}namespace 키워드를 사용하는 현대적인 선호 형태로 별칭이 지정되었습니다.// ✅ 올바른 구문namespace Foo { export const bar = 10;}namespace가 도입되었을 때 module 구문은 단순히 권장되지 않는 수준이었습니다. 몇 년 전부터 TypeScript 언어 서비스는 이 키워드를 지원 중단된 것으로 표시하고 대신 namespace를 제안하기 시작했습니다.namespace가 기대되는 곳에 module을 사용하는 것은 이제 엄격한 지원 중단 대상입니다. 이 변경은 module 블록이 레거시 TypeScript 구문과 충돌할 수 있는 잠재적인 ECMAScript 제안이기 때문에 필요합니다.// ✅ 여전히 완벽하게 작동합니다.declare module "some-module" { export function doSomething(): void;}asserts 키워드asserts 키워드는 임포트 단언 제안을 통해 JavaScript 언어에 제안되었으나, 결국 asserts 대신 with 키워드를 사용하는 임포트 속성(Import Attributes) 제안으로 변형되었습니다.asserts 구문은 이제 TypeScript 6.0에서 지원 중단되며, 이를 사용하면 오류가 발생합니다.// ❌ 지원 중단된 구문 - 이제 오류 발생.import blob from "./blahb.json" asserts { type: "json" }// ~~~~~~~// 오류: 임포트 단언(Import assertions)은 임포트 속성(Import attributes)으로 대체되었습니다. 'asserts' 대신 'with'를 사용하세요.with 구문을 사용하세요.// ✅ 새로운 임포트 속성 구문으로 작동합니다.import blob from "./blahb.json" with { type: "json" }no-default-lib 지시어/// <reference no-default-lib="true"/> 지시어는 그동안 많은 오해와 오용이 있었습니다. TypeScript 6.0에서 이 지시어는 더 이상 지원되지 않습니다. 이를 사용 중이었다면 대신 --noLib 또는 --libReplacement를 사용하는 것을 고려해 보세요.tsconfig.json이 존재할 때 커맨드 라인 파일 지정 시 오류 발생tsconfig.json이 있는 폴더에서 tsc foo.ts를 실행하면 설정 파일이 완전히 무시됩니다. 이는 입력 파일에 체크 및 출력 옵션이 적용될 것이라고 기대한 경우 매우 혼란스러울 수 있습니다.tsconfig.json이 포함된 디렉토리에서 파일 인자와 함께 tsc를 실행하면, 이 동작을 명시적으로 알리기 위해 오류가 발생합니다.error TS5112: tsconfig.json is present but will not be loaded if files are specified on commandline. Use '--ignoreConfig' to skip this error.tsconfig.json을 무시하고 TypeScript의 기본값으로 foo.ts를 컴파일하려는 것이 맞다면, 새로운 --ignoreConfig 플래그를 사용할 수 있습니다.tsc --ignoreConfig foo.ts"ignoreDeprecations": "6.0"을 설정하면 오류 없이 계속 작동하지만, 이러한 옵션들은 TypeScript 7.0(네이티브 TypeScript 포트)에서 완전히 제거될 예정입니다. TypeScript 6.0으로 업그레이드한 후 지원 중단 경고가 표시된다면, 프로젝트에 TypeScript 7.0을 도입(또는 네이티브 프리뷰 시도)하기 전에 이를 해결할 것을 강력히 권장합니다.
아직 댓글이 없습니다.
첫 번째 댓글을 작성해보세요!