Je compile toujours Typescript avec l'indicateur --noImplicitAny. Cela a du sens car je veux que ma vérification de type soit aussi serrée que possible.
Mon problème est qu'avec le code suivant, j'obtiens l'erreur Index signature of object type implicitly has an 'any' type
:
interface ISomeObject {
firstKey: string;
secondKey: string;
thirdKey: string;
}
let someObject: ISomeObject = {
firstKey: 'firstValue',
secondKey: 'secondValue',
thirdKey: 'thirdValue'
};
let key: string = 'secondKey';
let secondValue: string = someObject[key];
Il est important de noter que l'idée est que la variable clé vient d'ailleurs dans l'application et peut être n'importe laquelle des clés de l'objet.
J'ai essayé de convertir explicitement le type en:
let secondValue: string = <string>someObject[key];
Ou est-ce que mon scénario n'est tout simplement pas possible avec --noImplicitAny
?
la source
Une autre façon d'éviter l'erreur consiste à utiliser le cast comme ceci:
let secondValue: string = (<any>someObject)[key];
(Notez la parenthèse)Le seul problème est que ce type n'est plus sûr pour le type, car vous
any
. Mais vous pouvez toujours restituer le type correct.ps: J'utilise tapuscript 1.7, je ne suis pas sûr des versions précédentes.
la source
let secondValue: string = (someObject as any)[key];
TypeScript 2.1 a introduit une manière élégante de gérer ce problème.
Nous pouvons accéder à tous les noms de propriétés d'objets pendant la phase de compilation par
keyof
mot-clé (voir changelog ).Il vous suffit de remplacer le
string
type de variable parkeyof ISomeObject
. Le compilateur sait maintenant que lakey
variable est autorisée à contenir uniquement les noms de propriété deISomeObject
.Exemple complet:
Code en direct sur typescriptlang.org (
noImplicitAny
option set )Lectures complémentaires avec plus d'
keyof
usages .la source
key
commeconst key = (keyof ISomeObject)
= 'second' + 'Key'Le paramètre tsconfig suivant vous permettra d'ignorer ces erreurs - définissez-le sur true.
la source
--noImplicitAny
. Correspond parfaitement à la question de l'op.XMLHttpRequest
.keyof
opérateur TS2.1 peut aider à garder tout strict, voir la réponse de Piotr!La solution «keyof» mentionnée ci-dessus fonctionne. Mais si la variable n'est utilisée qu'une seule fois, par exemple pour parcourir un objet, etc., vous pouvez également la transtyper.
la source
utilisation
keyof typeof
la source
Similaire à la réponse de @Piotr Lewandowski, mais dans un
forEach
:la source
Argument of type '(field: "id" | "url" | "name") => void' is not assignable to parameter of type '(value: string, index: number, array: string[]) => void'
. Mon code ressemble à çaObject.keys(components).forEach((comp: Component) => {...}
, oùComponent
est un type (commeMyConfig
).Déclarez l'objet comme ceci.
la source
Pas d'indexeur? Faites le vôtre!
J'ai globalement défini cela comme un moyen facile de définir une signature d'objet.
T
peut êtreany
si nécessaire:J'ajoute juste en
indexer
tant que membre de la classe.Je me retrouve donc avec ceci:
L'avantage de faire cela est que vous récupérez le type approprié - de nombreuses solutions qui utilisent
<any>
perdront la saisie pour vous. N'oubliez pas que cela n'effectue aucune vérification d'exécution. Vous devrez toujours vérifier si quelque chose existe si vous ne savez pas avec certitude s'il existe.Si vous voulez être trop prudent et que vous utilisez,
strict
vous pouvez le faire pour révéler tous les endroits dont vous pourriez avoir besoin pour effectuer une vérification explicite non définie:Je ne trouve généralement pas cela nécessaire, car si j'ai une propriété de chaîne de quelque part, je sais généralement qu'elle est valide.
J'ai trouvé cette méthode particulièrement utile si j'ai beaucoup de code qui a besoin d'accéder à l'indexeur et que le typage peut être changé en un seul endroit.
Remarque: j'utilise le
strict
mode, etunknown
c'est vraiment nécessaire.Le code compilé le sera
indexer = this
, il est donc très similaire à la création de typographie_this = this
pour vous.la source
Record<T>
type à la place - je ne suis pas en mesure pour l'instant de rechercher les détails de cela, mais pour certains cas limités, cela peut mieux fonctionner.Créer une interface pour définir l'interface «indexeur»
Créez ensuite votre objet avec cet index.
Remarque: cela aura toujours les mêmes problèmes que d'autres réponses ont décrits en ce qui concerne l'application du type de chaque élément - mais c'est souvent exactement ce que vous voulez.
Vous pouvez définir le paramètre de type générique selon vos besoins:
ObjectIndexer< Dog | Cat>
Aire de jeux dactylographiée
Vous pouvez même l'utiliser dans une contrainte générique lors de la définition d'un type générique:
export class SmartFormGroup<T extends IndexableObject<any>> extends FormGroup
Ensuite,
T
à l'intérieur de la classe peut être indexé :-)la source
Dictionary
cela{ [key: string]: T }
, mais s'il y en a un, veuillez modifier cette question pour supprimer maObjectIndexer
.Déclarez le type dont sa clé est une chaîne et la valeur peut être quelconque, puis déclarez l'objet avec ce type et la peluche ne s'affichera pas
Votre code sera donc
la source
Aujourd'hui, la meilleure solution consiste à déclarer des types. Comme
la source
La solution la plus simple que j'ai pu trouver en utilisant Typescript 3.1 en 3 étapes est:
1) Faire l'interface
2) Faites une copie dactylographiée
3) Utilisez n'importe où (JSX inclus)
la source