Esistono diverse situazioni che ti daranno questo errore particolare. Nel caso dell'OP c'era un valore definito esplicitamente come una stringa . Quindi devo presumere che forse questo provenga da un menu a discesa, da un servizio Web o da una stringa JSON non elaborata.
In tal caso un cast semplice <Fruit> fruitString
o fruitString as Fruit
è l'unica soluzione (vedi altre risposte). Non saresti mai in grado di migliorarlo al momento della compilazione. [ Modifica: vedi la mia altra risposta su<const>
]!
Tuttavia è molto facile imbattersi in questo stesso errore quando si usano costanti nel codice che non sono mai state pensate per essere di tipo stringa . La mia risposta si concentra su quel secondo scenario:
Prima di tutto: perché le costanti di stringa "magiche" sono spesso migliori di un enum?
- Mi piace l'aspetto di una costante di stringa rispetto a un'enum: è compatta e "javascripty"
- Ha più senso se il componente in uso utilizza già costanti di stringa.
- Dover importare un "tipo enum" solo per ottenere un valore di enumerazione può essere problematico in sé
- Qualunque cosa faccia, voglio che sia compilata in modo sicuro, quindi se aggiungo rimuovi un valore valido dal tipo di unione o lo digito male, DOVREBBE dare un errore di compilazione.
Fortunatamente quando si definisce:
export type FieldErrorType = 'none' | 'missing' | 'invalid'
... in realtà stai definendo un'unione di tipi in cui'missing'
realtà è un tipo!
Mi capita spesso di imbattermi nell'errore "non assegnabile" se ho una stringa come 'banana'
nel mio dattiloscritto e il compilatore pensa che lo intendessi come una stringa, mentre volevo davvero che fosse di tipobanana
. La capacità del compilatore dipende dalla struttura del codice.
Ecco un esempio di quando ho ricevuto questo errore oggi:
// this gives me the error 'string is not assignable to type FieldErrorType'
fieldErrors: [ { fieldName: 'number', error: 'invalid' } ]
Non appena ho scoperto che 'invalid'
o 'banana'
potrebbe essere un tipo o una stringa ho capito che potevo semplicemente affermare una stringa in quel tipo . Fondamentalmente lanciarlo su se stesso e dire al compilatore che non voglio che sia una stringa !
// so this gives no error, and I don't need to import the union type too
fieldErrors: [ { fieldName: 'number', error: <'invalid'> 'invalid' } ]
Quindi, cosa c'è che non va nel 'casting' FieldErrorType
(o Fruit
)
// why not do this?
fieldErrors: [ { fieldName: 'number', error: <FieldErrorType> 'invalid' } ]
Il tempo di compilazione non è sicuro:
<FieldErrorType> 'invalidddd'; // COMPILER ALLOWS THIS - NOT GOOD!
<FieldErrorType> 'dog'; // COMPILER ALLOWS THIS - NOT GOOD!
'dog' as FieldErrorType; // COMPILER ALLOWS THIS - NOT GOOD!
Perché? Questo è dattiloscritto, quindi <FieldErrorType>
è un'affermazione e stai dicendo al compilatore che un cane è un FieldErrorType ! E il compilatore lo permetterà!
MA se fai quanto segue, il compilatore convertirà la stringa in un tipo
<'invalid'> 'invalid'; // THIS IS OK - GOOD
<'banana'> 'banana'; // THIS IS OK - GOOD
<'invalid'> 'invalidddd'; // ERROR - GOOD
<'dog'> 'dog'; // ERROR - GOOD
Fai attenzione agli stupidi errori di battitura come questo:
<'banana'> 'banan'; // PROBABLY WILL BECOME RUNTIME ERROR - YOUR OWN FAULT!
Un altro modo per risolvere il problema è lanciare l'oggetto genitore:
Le mie definizioni erano le seguenti:
tipo di esportazione FieldName = 'numero' | 'data di scadenza' | 'CVV'; tipo di esportazione FieldError = 'none' | 'mancante' | 'non valido'; tipo di esportazione FieldErrorType = {field: FieldName, errore: FieldError};
Diciamo che otteniamo un errore con questo (la stringa non è errore assegnabile):
fieldErrors: [ { field: 'number', error: 'invalid' } ]
Possiamo "affermare" l'intero oggetto in FieldErrorType
questo modo:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'invalid' } ]
Quindi evitiamo di doverlo fare <'invalid'> 'invalid'
.
E i refusi? Non afferma<FieldErrorType>
semplicemente ciò che è giusto essere di quel tipo. Non in questo caso - per fortuna il compilatore SARÀ lamentarsi se si esegue questa operazione, perché è abbastanza intelligente per sapere che è impossibile:
fieldErrors: [ <FieldErrorType> { field: 'number', error: 'dog' } ]
export type Fruit
?