Voici ce que j'ai dans fruit.ts
export type Fruit = "Orange" | "Apple" | "Banana"
J'importe maintenant fruit.ts dans un autre fichier dactylographié. Voici ce que j'ai
myString:string = "Banana";
myFruit:Fruit = myString;
Quand je fais
myFruit = myString;
J'obtiens une erreur:
Le type 'chaîne' n'est pas attribuable au type '"Orange" | "Apple" | "Banane"'
Comment puis-je attribuer une chaîne à une variable de type personnalisé Fruit?
javascript
typescript
angular
user6123723
la source
la source
export type Fruit
?Réponses:
Vous devrez le lancer :
Notez également que lorsque vous utilisez des littéraux de chaîne, vous ne devez utiliser qu'un seul
|
Éditer
Comme mentionné dans l'autre réponse de @Simon_Weaver, il est désormais possible de l'affirmer pour
const
:la source
const myFruit: Fruit = "Banana"
ferait l'affaire.let myFruit:Fruit = "Apple" let something:string = myFruit as string
Cela me donne une erreur: la conversion du type «Fruit» en type «string» peut être une erreur.as string
pièce. J'ai essayé votre code dans la cour de récréation et il n'y a aucune erreur.const myString: string = 'Bananaaa';
je n'obtiens pas d'erreurs de compilation à cause du casting ... n'y a-t-il aucun moyen de le faire en vérifiant la chaîne?Typescript
3.4
introduit la nouvelle assertion 'const'Vous pouvez maintenant empêcher que les types littéraux (par exemple
'orange'
ou'red'
) ne soient «élargis» au typestring
avec une prétendueconst
assertion.Vous pourrez faire:
Et puis il ne se transformera plus en un
string
- qui est la racine du problème dans la question.la source
let fruit = 'orange' as const;
en règle suivante sans angle de type-support affirmationLorsque vous faites ceci:
... vous créez un type appelé
Fruit
qui ne peut contenir que les littéraux"Orange"
,"Apple"
et"Banana"
. Ce type s'étendString
, il peut donc être attribué àString
. Cependant,String
ne s'étend PAS"Orange" | "Apple" | "Banana"
, donc il ne peut pas lui être attribué.String
est moins spécifique . Cela peut être n'importe quelle chaîne .Lorsque vous faites ceci:
...Ça marche. Pourquoi? Parce que le type réel de
myString
dans cet exemple est"Banana"
. Oui,"Banana"
c'est le type . Il est étenduString
donc il est assignable àString
. En outre, un type étend un type Union lorsqu'il étend l' un de ses composants. Dans ce cas"Banana"
,, le type s'étend"Orange" | "Apple" | "Banana"
car il étend l'un de ses composants. Par conséquent,"Banana"
est assignable à"Orange" | "Apple" | "Banana"
ouFruit
.la source
<'Banana'> 'Banana'
et cela va «lancer» une"Banana"
chaîne sur"Banana"
le type !!!<const> 'Banana'
ce qui est mieux :-)Je vois que c'est un peu vieux, mais il pourrait y avoir une meilleure solution ici.
Lorsque vous voulez une chaîne, mais que vous voulez que la chaîne ne corresponde qu'à certaines valeurs, vous pouvez utiliser des énumérations .
Par exemple:
Vous saurez maintenant que quoi qu'il arrive, myFruit sera toujours la chaîne "Banana" (ou toute autre valeur énumérable que vous choisissez). Ceci est utile pour beaucoup de choses, qu'il s'agisse de regrouper des valeurs similaires comme celle-ci ou de mapper des valeurs conviviales à des valeurs conviviales pour la machine, tout en appliquant et en restreignant les valeurs autorisées par le compilateur.
la source
let myFruit: Fruit = "Banana"
.Il existe plusieurs situations qui vous donneront cette erreur particulière. Dans le cas de l'OP, il y avait une valeur définie explicitement comme une chaîne . Je dois donc supposer que cela provient peut-être d'une liste déroulante, d'un service Web ou d'une chaîne JSON brute.
Dans ce cas, un simple casting
<Fruit> fruitString
oufruitString as Fruit
est la seule solution (voir les autres réponses). Vous ne pourrez jamais améliorer cela au moment de la compilation. [ Edit: Voir mon autre réponse sur<const>
]!Cependant, il est très facile de rencontrer cette même erreur lors de l'utilisation de constantes dans votre code qui ne sont jamais destinées à être de type chaîne . Ma réponse se concentre sur ce deuxième scénario:
Tout d'abord: pourquoi les constantes de chaîne «magiques» sont-elles souvent meilleures qu'une énumération?
Heureusement lorsque vous définissez:
export type FieldErrorType = 'none' | 'missing' | 'invalid'
... vous définissez en fait une union de types où
'missing'
est en fait un type!Je rencontre souvent l'erreur `` non assignable '' si j'ai une chaîne comme
'banana'
dans mon dactylographié et le compilateur pense que je l'ai signifiée comme une chaîne, alors que je voulais vraiment qu'elle soit de typebanana
. L'intelligence du compilateur dépendra de la structure de votre code.Voici un exemple de quand j'ai eu cette erreur aujourd'hui:
Dès que j'ai découvert cela
'invalid'
ou qu'il'banana'
pouvait s'agir d'un type ou d'une chaîne, j'ai réalisé que je pouvais simplement affirmer une chaîne dans ce type . Essentiellement, lancez-le sur lui - même et dites au compilateur non, je ne veux pas que ce soit une chaîne !Alors qu'est-ce qui ne va pas avec juste `` lancer '' vers
FieldErrorType
(ouFruit
)Le temps de compilation n'est pas sûr:
Pourquoi? Il s'agit d' un texte dactylographié, donc d'
<FieldErrorType>
une assertion et vous dites au compilateur qu'un chien est un FieldErrorType ! Et le compilateur le permettra!MAIS si vous faites ce qui suit, le compilateur convertira la chaîne en un type
Attention aux fautes de frappe stupides comme celle-ci:
Une autre façon de résoudre le problème consiste à convertir l'objet parent:
Mes définitions étaient les suivantes:
type d'exportation FieldName = 'nombre' | 'expirationDate' | «cvv»; type d'exportation FieldError = 'none' | «manquant» | 'invalide'; type d'exportation FieldErrorType = {champ: FieldName, erreur: FieldError};
Disons que nous obtenons une erreur avec ceci (la chaîne d'erreur non attribuable):
Nous pouvons `` affirmer '' l'objet entier
FieldErrorType
comme ceci:Alors on évite d'avoir à faire
<'invalid'> 'invalid'
.Mais qu'en est-il des fautes de frappe? Ne fonctionne pas
<FieldErrorType>
simplement affirmer ce qui est sur le droit d'être de ce type. Pas dans ce cas - heureusement , le compilateur FERA porter plainte si vous faites cela, car il est assez intelligent pour savoir qu'il est impossible:la source
Toutes les réponses ci-dessus sont valides, cependant, dans certains cas, le type littéral chaîne fait partie d'un autre type complexe. Prenons l'exemple suivant:
Vous avez plusieurs solutions pour résoudre ce problème. Chaque solution est valide et a ses propres cas d'utilisation.
1) La première solution est de définir un type pour la taille et de l'exporter depuis le fichier foo.ts. C'est bien si vous devez travailler seul avec le paramètre size. Par exemple, vous avez une fonction qui accepte ou renvoie un paramètre de type size et vous souhaitez le saisir.
2) La deuxième option consiste simplement à le convertir en type ToolbarTheme. Dans ce cas, vous n'avez pas besoin d'exposer l'intérieur de ToolbarTheme si vous n'en avez pas besoin.
la source
Si vous effectuez un cast en un
dropdownvalue[]
lors de la simulation de données, par exemple, composez-le sous la forme d'un tableau d'objets avec des propriétés de valeur et d'affichage.exemple :
la source
J'étais confronté au même problème, j'ai apporté les modifications ci-dessous et le problème a été résolu.
Ouvrez le fichier watchQueryOptions.d.ts
Changer le type de requête any au lieu de DocumentNode , idem pour la mutation
Avant:
Après:
la source