ProgrammazioneSviluppatore Frontend

Come funziona il meccanismo di tipizzazione dei moduli JavaScript importati in TypeScript? Come tipizzare un'importazione se il file JS sorgente non contiene tipi? Quali sono le sfide e i rischi nell'uso di any nell'importazione?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

Storia della questione:

TypeScript è progettato per aggiungere tipizzazione statica alle applicazioni JS esistenti. Si pone quindi la domanda: come tipizzare un'importazione se stiamo collegando un modulo esterno o un nostro stesso modulo scritto in JavaScript puro, dove i tipi non sono presenti? In questo caso TypeScript utilizza i cosiddetti declaration files (.d.ts) oppure deduce i tipi automaticamente (a volte in modo errato).

Problema:

Se durante l'importazione TypeScript non trova una descrizione di tipo adeguata, la variabile assume il tipo any, il che significa una totale perdita di sicurezza tipologica. Questo può portare a errori che il compilatore non rileverà, causando bug durante il runtime. Spesso gli sviluppatori dimenticano di dichiarare esplicitamente i tipi per le funzioni/gli oggetti importati.

Soluzione:

  1. Per i propri moduli JS, è possibile scrivere le dichiarazioni di tipo manualmente (file .d.ts).
  2. Per librerie popolari esistono spesso pacchetti @types/.
  3. È possibile dichiarare esplicitamente i tipi all'importazione, descrivendo da soli la struttura dell'oggetto necessario.
  4. Si raccomanda di evitare any e, se non si può evitare, limitare al minimo l'ambito di utilizzo.

Esempio di codice:

// 1. Tipizzazione esplicita dell'importazione del modulo JS import myFunc from './myLib'; declare function myFunc(x: number): boolean; // 2. Importazione da un modulo JS per il quale è stato creato il file myLib.d.ts con export function myFunc(x: number): boolean; import { myFunc } from './myLib'; // 3. Importiamo un modulo senza tipizzazione e descriviamo esplicitamente il tipo import * as legacy from './legacy'; const typedLegacy: { runTask: (name: string) => void } = legacy;

Caratteristiche principali:

  • In assenza di dichiarazioni, il valore importato assume per default il tipo any, compromettendo la sicurezza tipologica.
  • L'approccio migliore è la creazione di file .d.ts per moduli esterni/banche dati.
  • Se necessario, è possibile dichiarare localmente funzioni/moduli esterni tramite declare/interfacce.

Domande insidiose.

Può TypeScript dedurre automaticamente i tipi di un modulo JS importato senza dichiarazioni?

No, se il file è scritto in JavaScript, senza dichiarazioni di tipo TypeScript è costretto a presumere any e perde informazioni sui tipi, tranne per casi triviali (export const x = 1;).

È possibile "estendere" i tipi importati se nuovi campi appaiono nel modulo JS?

Solo se aggiorni il file di dichiarazione (.d.ts). Se i tipi sono fissati in .d.ts, TypeScript li userà come "verità", eventuali nuovi campi rimarranno senza tipizzazione o porteranno a un errore.

È sicuro importare un modulo JS esterno in un progetto TypeScript se non esistono @types/ e dichiarazioni?

No, questo diminuisce drasticamente la sicurezza: l'intero lavoro con l'importazione risulta untyped (any), il compilatore non genererà errori, anche se il modulo non è disponibile o l'API è cambiata. Lavorare con tali moduli è accettabile solo come soluzione temporanea, con tipizzazione esplicita o isolamento del codice.

Errori tipici e anti-pattern

  • Dimenticanza delle dichiarazioni (.d.ts) per pacchetti esterni.
  • Fiducia cieca nell'implicit any durante l'importazione di moduli JS.
  • Violazione dei confini del codice type-safe.

Esempio dalla vita reale

Caso negativo

Un sviluppatore importa una libreria JS esterna senza dichiarazioni, utilizzando l'API con sicurezza, ottenendo il tipo any. Dopo l'aggiornamento della libreria, la firma dei metodi cambia, ma non si verificano errori, solo bug durante il runtime.

Vantaggi:

  • Rapido e semplice collegare qualsiasi modulo JS.

Svantaggi:

  • Nessuna garanzia di sicurezza tipologica, gli errori rimangono sfuggenti fino all'esecuzione.

Caso positivo

Si crea un file di dichiarazione .d.ts o si aggiunge un pacchetto @types/, la descrizione dell'API corrisponde esattamente al modulo JS sorgente. Tutti i metodi importati sono tipizzati, l'IDE offre suggerimenti di completamento automatico, eventuali discrepanze mostrano un errore di compilazione.

Vantaggi:

  • Sicurezza tipologica, avviso di errori prima dell'esecuzione.
  • Supporto per completamento automatico e documentazione direttamente nel codice.

Svantaggi:

  • Richiede tempo per scrivere .d.ts, supporto dei tipi durante gli aggiornamenti del modulo JS.