web-dev-qa-db-fra.com

La propriété 'valeur' ​​n'existe pas sur la valeur de type 'HTMLElement'

Je joue avec TypeScript et j'essaie de créer un script qui mettra à jour un élément p lorsque le texte est entré dans une zone de saisie.

Le HTML ressemble à ce qui suit:

<html>
    <head>
    </head>
    <body>
        <p id="greet"></p>
        <form>
            <input id="name" type="text" name="name" value="" onkeyup="greet('name')" />
        </form>
    </body>
    <script src="greeter.js"></script>
</html>

Et le fichier greeter.ts:

function greeter(person)
{
    return "Hello, " + person;
}

function greet(elementId)
{
    var inputValue = document.getElementById(elementId).value;

    if (inputValue.trim() == "")
        inputValue = "World";

    document.getElementById("greet").innerText = greeter(inputValue);
}

Lorsque je compile avec tsc, le message d'erreur suivant s'affiche:

/home/bjarkef/sandbox/greeter.ts(8,53): The property 'value' does not exist on value of type 'HTMLElement'

Cependant, le compilateur génère un fichier javascript, qui fonctionne très bien en chrome.

Comment puis-je avoir cette erreur? Et comment puis-je la corriger?

De plus, où puis-je rechercher quelles propriétés sont valides sur un 'HTMLElement' selon le manuscrit?

Notez que javascript et TypeScript étant nouveaux pour moi, il se peut que je manque quelque chose d’évident. :)

192

Basé sur la réponse de Tomasz Nurkiewiczs, le "problème" est que TypeScript est typé. :) Ainsi, la document.getElementById() renvoie le type HTMLElement qui ne contient pas de propriété value. Le sous-type HTMLInputElement contient cependant la propriété value.

Donc, une solution consiste à convertir le résultat de getElementById() en HTMLInputElement comme ceci:

var inputValue = (<HTMLInputElement>document.getElementById(elementId)).value;

<> est l'opérateur de transtypage dans TypeScript. Voir la question TypeScript: casting HTMLElement .

Le javascript résultant de la ligne ci-dessus ressemble à ceci:

inputValue = (document.getElementById(elementId)).value;

c'est-à-dire ne contenant aucune information de type.

352

Si vous utilisez Réagissez, vous pouvez utiliser l'opérateur as.

let inputValue = (document.getElementById(elementId) as HTMLInputElement).value;
42
Michael

Essayez de transtyper l'élément que vous souhaitez mettre à jour vers HTMLInputElement. Comme indiqué dans les autres réponses, vous devez indiquer au compilateur qu'il s'agit d'un type spécifique de HTMLElement:

var inputElement = <HTMLInputElement>document.getElementById('greet');
inputElement.value = greeter(inputValue);
38
woodysan

Le problème est ici:

document.getElementById(elementId).value

Vous savez que HTMLElement renvoyé par getElementById() est en réalité une instance de HTMLInputElement qui en hérite, car vous transmettez un ID d'élément d'entrée. De même dans Java statiquement typé, cela ne compilera pas:

public Object foo() {
  return 42;
}

foo().signum();

signum() est une méthode de Integer, mais le compilateur ne connaît que le type statique de foo(), qui est Object. Et Object n'a pas de méthode signum().

Mais le compilateur ne peut pas le savoir, il ne peut se baser que sur des types statiques, pas sur le comportement dynamique de votre code. Et pour autant que le compilateur le sache, le type de l'expression document.getElementById(elementId) n'a pas la propriété value. Seuls les éléments d'entrée ont une valeur.

Pour une vérification de référence HTMLElement et HTMLInputElement dans MDN. Je suppose que TypeScript est plus ou moins compatible avec ceux-ci.

15
Tomasz Nurkiewicz

Une solution rapide pour cela consiste à utiliser [] pour sélectionner l'attribut.

function greet(elementId) {
    var inputValue = document.getElementById(elementId)["value"];
    if(inputValue.trim() == "") {
        inputValue = "World";
    }
    document.getElementById("greet").innerText = greeter(inputValue);
}

Je viens d'essayer quelques méthodes et trouver cette solution,
Je ne sais pas quel est le problème derrière votre script original.

Pour référence, vous pouvez vous référer au message de Tomasz Nurkiewicz.

14
inDream

Exemple mis à jour:

const inputElement: HTMLInputElement = document.getElementById('greet') as HTMLInputElement
const inputValue: string = InputElement.value

Documentation:

TypeScript - Types de base - Assertions de type

12
Leo

Aussi, pour toute personne utilisant des propriétés telles que des accessoires ou des références sans votre "DocgetId", vous pouvez:

("" as HTMLInputElement).value;

Où les guillemets inversés sont la valeur de vos accessoires, un exemple serait comme ceci:

var val = (this.refs.newText as HTMLInputElement).value;
alert("Saving this:" + val);
11
KidKode