Torna al blog

TypeScript 5.9: tsc --init Rinnovato, import defer e Expandable Hovers - Release 2025

Scopri TypeScript 5.9: tsconfig.json minimal, import defer per deferred evaluation, --module node20, expandable hovers, DOM API summaries e optimizations 2025.

Edoardo Midali

Edoardo Midali

Developer Β· Content Creator

9 min di lettura
TypeScript 5.9: tsc --init Rinnovato, import defer e Expandable Hovers - Release 2025

TypeScript 5.9 introduce un tsconfig.json minimal e moderno, supporto per import defer (deferred module evaluation), --module node20, expandable hovers nell'editor, DOM API summaries, e significative optimizations per performance. Un update focalizzato su developer experience!

🎯 Novità Principali

Nuovo tsc --init Minimal e Moderno

tsconfig.json ripensato - meno commenti, piΓΉ pratico!

Prima (Vite 5.8)

// ❌ 100+ righe di commenti
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig to read more about this file */
    /* Projects */
    // "incremental": true,
    // "composite": true,
    // "tsBuildInfoFile": "./.tsbuildinfo",
    // "disableSourceOfProjectReferenceRedirect": true,
    // ... 90+ righe di opzioni commentate
  }
}

Dopo (TypeScript 5.9)

// βœ… Minimal e prescriptive!
{
  // Visit https://aka.ms/tsconfig to read more about this file
  "compilerOptions": {
    // File Layout
    // "rootDir": "./src",
    // "outDir": "./dist",

    // Environment Settings
    // See also https://aka.ms/tsconfig_modules
    "module": "nodenext",
    "target": "esnext",
    "types": [],

    // For nodejs:
    // "lib": ["esnext"],
    // "types": ["node"],
    // and npm install -D @types/node

    // Other Outputs
    "sourceMap": true,
    "declaration": true,
    "declarationMap": true,

    // Stricter Typechecking Options
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,

    // Style Options
    // "noImplicitReturns": true,
    // "noImplicitOverride": true,
    // "noUnusedLocals": true,
    // "noUnusedParameters": true,
    // "noFallthroughCasesInSwitch": true,
    // "noPropertyAccessFromIndexSignature": true,

    // Recommended Options
    "strict": true,
    "jsx": "react-jsx",
    "verbatimModuleSyntax": true,
    "isolatedModules": true,
    "noUncheckedSideEffectImports": true,
    "moduleDetection": "force",
    "skipLibCheck": true
  }
}

Cambio di filosofia:

# ❌ Prima: Scopri opzioni via tsconfig generato
# Problema: troppo verbose, si cancella tutto subito

# βœ… Ora: Scopri opzioni via editor autocomplete + docs
# Beneficio: config clean, docs online sempre aggiornate

Opzioni moderne di default:

Opzione Valore PerchΓ©
module "nodenext" Most projects use modules
target "esnext" Modern runtimes support latest ES
types [] Limit unnecessary @types loading
moduleDetection "force" Every file is a module
jsx "react-jsx" Modern JSX transform
strict true Best type safety
isolatedModules true Bundler compatibility

Benefici:

  • βœ… Meno friction - Config pronti per l'uso
  • βœ… Best practices - Opzioni moderne di default
  • βœ… Leggibile - No more 100+ righe commentate
  • βœ… Discoverable - Editor autocomplete + online docs

Support for import defer

Deferred module evaluation per lazy loading!

// βœ… TypeScript 5.9 - import defer
import defer * as feature from "./some-feature.js";

// ❌ Questi NON funzionano con defer
import defer { doSomething } from "./feature.js"; // Named import
import defer defaultExport from "./feature.js"; // Default import

Come Funziona

Module con side effects:

// ./some-feature.ts
initializationWithSideEffects();

function initializationWithSideEffects() {
  specialConstant = 42;
  console.log("Side effects have occurred!");
}

export let specialConstant: number;

Normal import vs import defer:

// ❌ Normal import - Side effects IMMEDIATI
import * as feature from "./some-feature.js";
// β†’ Console: "Side effects have occurred!" βœ“
console.log("App started");
// β†’ Console: "App started"

// βœ… import defer - Side effects DEFERRED
import defer * as feature from "./some-feature.js";
// β†’ Nessun console log ancora!
console.log("App started");
// β†’ Console: "App started"

// Side effects accadono SOLO quando accedi al namespace
console.log(feature.specialConstant); // 42
// β†’ Console: "Side effects have occurred!" βœ“

Use Cases

1. Conditional feature loading:

// βœ… Heavy feature caricato solo se necessario
import defer * as analytics from "./analytics.js";

function trackEvent(event: string) {
  if (ENABLE_ANALYTICS) {
    // Analytics module caricato SOLO qui!
    analytics.track(event);
  }
}

2. Platform-specific modules:

import defer * as nodeFeatures from "./node-features.js";
import defer * as browserFeatures from "./browser-features.js";

if (typeof window !== "undefined") {
  // Browser code caricato solo in browser
  browserFeatures.setupDOM();
} else {
  // Node code caricato solo in Node.js
  nodeFeatures.setupServer();
}

3. Performance optimization:

// App startup
import defer * as dashboard from "./dashboard.js";
import defer * as settings from "./settings.js";
import defer * as admin from "./admin.js";

// Modules caricati on-demand quando user naviga
router.on("/dashboard", () => dashboard.render());
router.on("/settings", () => settings.render());
router.on("/admin", () => admin.render());

Limitazioni:

// βœ… Solo module mode: preserve e esnext
{
  "compilerOptions": {
    "module": "preserve" // O "esnext"
  }
}

// ⚠️ TypeScript NON transpila import defer
// Richiede runtime o bundler che supporta la feature

Support for --module node20

Stable Node.js 20 mode (vs nodenext floating)!

// ❌ --module nodenext
// - Floating target: si aggiorna con future Node.js versions
// - Implies --target esnext (sempre latest)

// βœ… --module node20
// - Locked to Node.js v20 behavior
// - Implies --target es2023 (stabile)
// - Non cambierΓ  in futuro

Comparison:

Feature nodenext node20
Target Node Latest v20
Implies --target esnext es2023
Future updates βœ… Yes ❌ No
Stability Floating Locked

Config esempio:

{
  "compilerOptions": {
    // βœ… Stable Node.js 20 support
    "module": "node20",
    "moduleResolution": "node20"
    // Implies: "target": "es2023"
  }
}

Quando usare:

  • βœ… node20: Production apps su Node.js 20 LTS
  • βœ… nodenext: Libraries che vogliono latest features

Expandable Hovers (Preview)

Deep dive in tooltips senza jump-to-definition!

interface Options {
  theme: "light" | "dark";
  verbose: boolean;
  plugins: Plugin[];
}

interface Plugin {
  name: string;
  version: string;
  config: Record<string, unknown>;
}

function drawButton(options: Options): void {
  // Hover su "options" β†’
}

Prima (TypeScript 5.8):

(parameter) options: Options

Dopo (TypeScript 5.9):

β”Œβ”€ (parameter) options: Options ───────────────────┐
β”‚ [+] Expand                                        β”‚
β”‚                                                   β”‚
β”‚ // Hover tooltip con + button                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

// Click su [+] β†’

β”Œβ”€ (parameter) options: Options ───────────────────┐
β”‚ [-] Collapse                                      β”‚
β”‚                                                   β”‚
β”‚ interface Options {                               β”‚
β”‚   theme: "light" | "dark"                         β”‚
β”‚   verbose: boolean                                β”‚
β”‚   plugins: Plugin[] [+]  ← Click per espandere!   β”‚
β”‚ }                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

// Click su plugins [+] β†’

β”Œβ”€ (parameter) options: Options ───────────────────┐
β”‚ [-] Collapse                                      β”‚
β”‚                                                   β”‚
β”‚ interface Options {                               β”‚
β”‚   theme: "light" | "dark"                         β”‚
β”‚   verbose: boolean                                β”‚
β”‚   plugins: Plugin[] [-]                           β”‚
β”‚     interface Plugin {                            β”‚
β”‚       name: string                                β”‚
β”‚       version: string                             β”‚
β”‚       config: Record<string, unknown>             β”‚
β”‚     }                                             β”‚
β”‚ }                                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Benefici:

  • βœ… No jump-to-definition - Esplora types in-place
  • βœ… Progressive disclosure - Espandi solo cosa serve
  • βœ… Faster workflow - Meno context switching

VS Code setting:

{
  // Enable expandable hovers
  "typescript.experimental.expandableHovers": true
}

Configurable Maximum Hover Length

Hovers piΓΉ lunghi e informativi!

// ❌ Prima - Hover troncato troppo presto
// hover su complexType β†’
type ComplexType = ... // [Truncated]

// βœ… Ora - Default hover length molto piΓΉ grande
type ComplexType = {
  field1: string;
  field2: number;
  field3: Array<...>;
  // ... molto piΓΉ contenuto visibile!
};

VS Code setting:

{
  // Customize hover length (default ora piΓΉ grande!)
  "typescript.hover.maximumLength": 100000 // Caratteri
}

DOM API Summary Descriptions

Tooltips informativi per DOM APIs!

// ❌ Prima
// hover su addEventListener β†’
addEventListener(type: string, listener: EventListener): void

// βœ… Ora
// hover su addEventListener β†’
/**
 * Registers an event handler to be called whenever
 * the specified event is delivered to the target.
 *
 * @see https://developer.mozilla.org/docs/Web/API/EventTarget/addEventListener
 */
addEventListener(type: string, listener: EventListener): void

Coverage:

  • βœ… DOM manipulation APIs
  • βœ… Web APIs (Fetch, WebSocket, etc.)
  • βœ… Browser APIs (Storage, Navigator, etc.)
  • βœ… Linked to MDN documentation

πŸ“Š Performance Optimizations

Cache Instantiations on Mappers

Massive speedup per complex generic types!

// Prima (TypeScript 5.8)
// - Type instantiations ripetute piΓΉ volte
// - Zod, tRPC: slowdowns + "excessive instantiation depth"

// Dopo (TypeScript 5.9)
// - Instantiations cached e riutilizzate
// - Meno work + meno allocations

Impact:

  • ⚑ Zod schemas - Checking molto piΓΉ veloce
  • ⚑ tRPC procedures - Type inference velocizzato
  • ⚑ Complex generics - No piΓΉ excessive depth errors

Avoiding Closure Creation

11% speedup su file existence checks!

// ❌ Prima - Function allocation ad ogni check
function fileExists(path: string) {
  return existsUsingSource((p) => checkFile(p)); // ❌ Closure created
}

// βœ… Ora - Direct function reference
function fileExists(path: string) {
  return existsUsingSource(checkFile); // βœ… No closure
}

Impact:

  • ⚑ Large projects - 11% faster type checking
  • ⚑ Monorepos - Significativo su migliaia di files

πŸ”„ Breaking Changes & Migration

lib.d.ts Changes

ArrayBuffer type changes - potrebbero causare errori!

// ❌ Ora genera errori:
function processBuffer(buffer: ArrayBufferLike) {
  someFunc(buffer);
  // ❌ Error TS2345: Argument of type 'ArrayBufferLike'
  //    is not assignable to parameter of type 'ArrayBuffer'
}

// βœ… Fix 1: Tipo piΓΉ specifico
function processBuffer(buffer: Uint8Array<ArrayBuffer>) {
  someFunc(buffer.buffer); // βœ… Access .buffer property
}

// βœ… Fix 2: Node.js Buffer
import { Buffer } from "node:buffer";

function processNodeBuffer(buffer: Buffer) {
  // Aggiorna @types/node alla latest!
  someFunc(buffer.buffer);
}

Update @types/node:

npm update @types/node --save-dev

Type Argument Inference Changes

// ❌ Possibili nuovi errori per "type variable leaks"

// Fix: Aggiungi explicit type arguments
someGenericFunction<ExpectedType>(arg);

πŸ’‘ Conclusioni

TypeScript 5.9 Γ¨ un developer experience upgrade:

βœ… tsc --init moderno - Config minimal e prescriptive βœ… import defer - Deferred module evaluation βœ… --module node20 - Stable Node.js 20 mode βœ… Expandable hovers - Deep type exploration in tooltips βœ… DOM summaries - Informative API documentation βœ… Performance - Cache instantiations + optimizations βœ… Better tooltips - Configurable hover length

Performance gains:

  • ⚑ Zod/tRPC: Massive speedup con cached instantiations
  • ⚑ Large projects: 11% faster type checking
  • ⚑ Startup time: Deferred imports per lazy loading

Inizia ora:

# Update TypeScript
npm install typescript@5.9 --save-dev

# Generate new tsconfig
npx tsc --init

# Enable experimental features in VS Code
{
  "typescript.experimental.expandableHovers": true,
  "typescript.hover.maximumLength": 100000
}