Innanzitutto, per assicurarci che stiamo parlando delle stesse cose, vorrei iniziare con alcune definizioni.
La tipizzazione statica significa che gli errori di tipo sono riportati in fase di compilazione, mentre la digitazione dinamica significa che gli errori di tipo sono riportati in fase di esecuzione.
Duck typing significa che una parte di codice richiede che un oggetto supporti le operazioni che vengono utilizzate e nient'altro.
La tipizzazione strutturale richiede che un oggetto supporti un determinato insieme di operazioni (anche se alcune di esse non possono essere utilizzate).
La tipizzazione nominale richiede che l'oggetto sia esattamente del tipo specificato o che sia un sottotipo di quel tipo.
Quindi, come puoi vedere, la tipizzazione strutturale è più severa della digitazione anatra e la digitazione nominale è più rigida di quella strutturale.
Ora parlerò di il linguaggio TypeScript , perché illustra bene la maggior parte di queste opzioni.
Considera il seguente programma TypeScript:
interface Person {
Name : string;
Age : number;
}
function greet(person : Person) {
alert("Hello, " + person.Name);
}
greet({ Name: "svick" });
Poiché l'oggetto passato a greet
non ha la proprietà Age
, ciò causa un errore in fase di compilazione, a dimostrazione che TypeScript utilizza tipizzazione strutturale statica .
Nonostante l'errore, il codice sopra in realtà viene compilato sul seguente JavaScript, che funziona perfettamente:
function greet(person) {
alert("Hello, " + person.Name);
}
greet({ Name: "svick" });
Questo dimostra che TypeScript usa anche typing anatra dinamico .
Se il codice invece è compilato in modo simile a:
function greet(person) {
if (!(typeof(person.Name) == 'string' && typeof(person.Age) == 'number'))
throw 'TypeError';
alert("Hello, " + person.Name);
}
Quindi questo sarebbe un esempio di tipizzazione strutturale dinamica , perché controlla che l'oggetto abbia le proprietà richieste dei tipi richiesti, anche se la funzione stessa non li richiede.
Se è compilato per:
function greet(person) {
if (!(person instanceof Person))
throw 'TypeError'
alert("Hello, " + person.Name);
}
Sarebbe un esempio di tipizzazione nominale dinamica , perché controlla il nome del tipo dell'oggetto, non la sua struttura.
Ciò che questo dimostra è che la digitazione dinamica senza anatra è possibile (sia strutturale che nominale). Ma questo approccio non viene usato molto spesso, perché combina principalmente gli svantaggi della digitazione non anatra (devi specificare i tipi in modo esplicito, meno flessibile) e la digitazione dinamica (gli errori di tipo vengono visualizzati solo in fase di esecuzione e solo nel codice che viene effettivamente eseguito) ).
Se vuoi aggiungere annotazioni di tipo per rendere possibile la digitazione non anatra, puoi anche controllare i tipi in fase di compilazione.