Differenza tra '!' e '?' in TypeScript
Class Employee {
firstName: string;
lastName!: string;
middleName?: string;
}
Qual è la differenza in questi 3 diversi campi di Employee
classe?
Esempio dal vivo
Risposte
Il ?
in quella posizione contrassegna la proprietà facoltativa .
Il !
in quella posizione è l' affermazione definitiva di assegnazione . È una sorta di versione a livello di dichiarazione dell'operatore di asserzione non nullo , ma utilizzato su una proprietà (può essere utilizzato anche su variabili) piuttosto che su un'espressione.
Ci sono due - o forse tre - errori in questo esempio:
Class
dovrebbe essereclass
; JavaScript e TypeScript fanno distinzione tra maiuscole e minuscole.Hai bisogno di un inizializzatore su
firstName
(o di un costruttore che lo assegni incondizionatamente).L'
!
onlastName
racconta dattiloscritto chelastName
sarà sicuramente assegnato, sopprimendo il tipo di errore che stai ricevendo perfirstName
, ma nulla (nell'esempio) in realtà fa l'assegnazione che l'utilizzo di!
là promesse dattiloscritto si sa per certo che si sta facendo.
Modifica: il codice che hai collegato in seguito si occupa di # 1 e # 2 sopra, ma non # 3. TypeScript non avvisa che lastName
non viene mai assegnato e assume che il suo valore sia una stringa, quando in realtà non è lì e quindi la lettura del suo valore risulterà in undefined
.
Sono ben nascosti nella documentazione di TypeScript .
?
è descritto sulle interfacce , contrassegna una proprietà opzionale .
!
è l' operatore di asserzione definita . Indica al compilatore che la proprietà è impostata (no null
o undefined
) anche se le analisi di TypeScript non possono rilevarlo.
A proposito, Class
non è una parola chiave TypeScript o JavaScript e produce un errore in quella posizione. La parola chiave per dichiarare una classe è class
. Gli identificatori e le parole chiave TypeScript e JavaScript fanno distinzione tra maiuscole Class
e minuscole ( e class
sono cose diverse).
Quando si ha l'opzione del compilatore strictNullChecks: false
Se hai strictNullChecks: false
nel tuo tsconfig.json
allora sono esattamente gli stessi poiché avere strictNullChecks
disabilitato significa che tutti i campi sono nulli o indefiniti come valori validi.
Quando si ha l'opzione del compilatore strictNullChecks: true
class Employee {
firstName: string;
lastName!: string;
middleName?: string;
}
firstName: string
significa che firstName
deve essere un file string
. null
o undefined
non sono valori validi per firstName.
Tutti i campi avranno un valore predefinito, undefined
questo comporterà un erroreProperty 'firstName' has no initializer and is not definitely assigned in constructor
Per mettere a tacere l'errore è necessario modificare la dichiarazione firstName: string = 'Some default value'
o aggiungere un costruttore e assegnargli un valore nel costruttore.
constructor() {
this.firstName = 'some default value';
}
Ora per il! sintassi. La lastName!: string
sintassi è simile a come lastName: string
in quanto dice fondamentalmente che string
è l'unico tipo consentito. null
e undefined
non sono ammessi. Ma metterà a tacere il compilatore sull'errore di assegnazione definito. Diciamo che hai il seguente codice.
classe Employee {firstName: string; lastName !: string; middleName ?: string;
constructor() {
// This will silence the compiler about first name not initialized
this.firstName = 'some default value';
// The compiler cannot tell that lastName is assigned in init() function
this.init();
}
private init(): void {
this.lastName = 'some default value';
}
}
Nel codice precedente, lastName
viene assegnato definitivamente in constructor
via la this.init()
chiamata. Tuttavia il compilatore non può saperlo. Quindi aggiungendo il! in pratica sta dicendo al compilatore "taci, so cosa sto facendo" . Spetta quindi a te garantire la correttezza del tuo codice.
Informazioni sulla middleName?: string
sintassi. Questo è esattamente lo stesso di middleName: string | undefined
; Poiché tutti i valori hanno il valore predefinito di undefined
, il compilatore non si lamenterà del fatto che middleName
non è assegnato.