La propiedad 'valor' no existe en el valor de tipo 'HTMLElement'

235

Estoy jugando con el mecanografiado y estoy tratando de crear un script que actualice un elemento p a medida que el texto se ingresa en un cuadro de entrada.

El html tiene el siguiente aspecto:

<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>

Y el greeter.tsarchivo:

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);
}

Cuando compilo con tscme sale el siguiente "error":

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

Sin embargo, el compilador genera un archivo javascript, que funciona bien en Chrome.

¿Cómo es que obtengo este error? ¿Y cómo puedo arreglarlo?

Además, ¿dónde puedo buscar qué propiedades son válidas en un 'HTMLElement'mecanografiado según?

Tenga en cuenta que soy muy nuevo en javascript y mecanografiado, por lo que es posible que me falte algo obvio. :)

Bjarke Freund-Hansen
fuente

Respuestas:

448

Según la respuesta de Tomasz Nurkiewiczs, el "problema" es que el mecanografiado es seguro. :) Entonces, document.getElementById()devuelve el tipo HTMLElementque no contiene una valuepropiedad. HTMLInputElementSin embargo, el subtipo contiene la valuepropiedad.

Por lo que una solución es emitir el resultado de getElementById()que HTMLInputElementde esta manera:

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

<>es el operador de conversión en mecanografiado. Vea la pregunta TypeScript: casting HTMLElement .

El javascript resultante de la línea anterior se ve así:

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

es decir, no contiene información de tipo.

Bjarke Freund-Hansen
fuente
¿tiene alguna lista a qué elemento de html pertenece para qué tipo de mecanografiado? en caso afirmativo, ¡por favor publíquelo será útil para alguien! Gracias por la gran respuesta.
Pardeep Jain
1
Esta solución rompe mi código por completo; dice que lo que venga después "no es una función". No entiendo el razonamiento detrás de la forma en que TS maneja esto; dado que getElementById puede devolver cualquier tipo de elemento, cualquiera debe ser aceptado por defecto.
tortugas son lindas
@TurtlesAreCute Tengo curiosidad acerca de cómo esta solución rompió su código. Esperemos que un año después haya encontrado una solución, pero el envío a HTMLInputElement debería haber funcionado.
Michaël Polla
En mi caso, tuve que cambiarlo a HTMLAnchorElement.
Wildhammer
@Wildhammer ¡Porque tu elemento no era un elemento de entrada! El OP es.
Auspex
68

Si está utilizando react, puede usar el asoperador.

let inputValue = (document.getElementById(elementId) as HTMLInputElement).value;
Miguel
fuente
3
Por alguna razón, la respuesta aceptada aquí me planteó el siguiente error: el elemento JSX 'HTMLInputElement' no tiene una etiqueta de cierre correspondiente. Esta es la respuesta que funcionó para mí.
NigelTufnel
1
La razón es porque en los archivos tsx no puede usar los <>operadores para emitir, ya que estos se usan en React. Entonces debe usarlo como: basarat.gitbooks.io/typescript/docs/types/…
Powderham
Aunque esto no funcionó para mí, me dirigió en la dirección correcta :) ¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡!!!
Simon Price
40

Intente transmitir el elemento que desea actualizar a HTMLInputElement. Como se indicó en las otras respuestas, debe insinuarle al compilador que este es un tipo específico de elemento HTMLE:

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

Una solución rápida para esto es usar [] para seleccionar el atributo.

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

Solo pruebo algunos métodos y descubro esta solución,
no sé cuál es el problema detrás de su script original.

Como referencia, puede consultar la publicación de Tomasz Nurkiewicz.

en el sueño
fuente
La respuesta adecuada a la pregunta me ayudó mucho.
Monir Khan
15

El problema está aquí:

document.getElementById(elementId).value

Sabes que HTMLElementdevuelto getElementById()es en realidad una instancia de HTMLInputElementheredar de él porque estás pasando una ID del elemento de entrada. Del mismo modo, en Java estáticamente tipado, esto no compilará:

public Object foo() {
  return 42;
}

foo().signum();

signum()es un método de Integer, pero el compilador solo conoce el tipo estático de foo(), que es Object. Y Objectno tiene un signum()método.

Pero el compilador no puede saber eso, solo puede basarse en tipos estáticos, no en el comportamiento dinámico de su código. Y hasta donde el compilador sabe, el tipo de document.getElementById(elementId)expresión no tienevalue propiedad. Solo los elementos de entrada tienen valor.

Para una consulta de referencia HTMLElementy HTMLInputElementen MDN. Supongo que Typecript es más o menos consistente con estos.

Tomasz Nurkiewicz
fuente
Pero no estoy accediendo .valueen el elemento p, estoy accediendo a él en el inputelemento. ¿O me equivoco?
Bjarke Freund-Hansen
1
@bjarkef: estás llamando document.getElementById("greet")y tienes <p id="greet"></p>...
Tomasz Nurkiewicz
Estoy llamando document.getElementById("greet").innerTextque debe ser perfectamente válido, solo estoy accediendo a la valuepropiedad en el elemento de entrada en la línea que contiene: var inputValue = document.getElementById(elementId).value;in greet(elementId)y que se llama en el html onkeyup="greet('name')"en el formulario de entrada. Así que creo que está leyendo mal el código, corríjame si me equivoco. :)
Bjarke Freund-Hansen
@bjarkef: lo siento, tenías razón. He reescrito mi respuesta, ¡mira!
Tomasz Nurkiewicz
1
Ah, esto tiene sentido. Entonces, ¿debo emitir el valor devuelto getElementByIdy cómo lo hago en mecanografiado? ¿O hay otro método que el getElementByIdque devuelve HTMLInputElement?
Bjarke Freund-Hansen
11

También para cualquier persona que use propiedades como accesorios o referencias sin sus "DocgetId's", entonces puede:

("" as HTMLInputElement).value;

Donde las comillas invertidas es el valor de sus accesorios, un ejemplo sería así:

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

Si está usando angular, puede usar:

const element = document.getElementById('elemId') as HTMLInputElement;
Rohit Grover
fuente
1

Este trabajo para mi:

let inputValue = (swal.getPopup().querySelector('#inputValue ')as HTMLInputElement).value
Juan Pablo
fuente
Necesita formato
Standin.Wolf
-1

Problema:

error La propiedad 'text' no existe en el tipo 'HTMLElement'

Solución: a máquina de escribir necesitamos fundido document.getElementById()que devuelve el tipo HTMLElementde< HTMLScriptElement >

Por lo tanto, podemos hacerlo de la siguiente manera para resolver el error como se esperaba por typescript.js

Code: var content: string = ( < HTMLScriptElement > document.getElementById(contentId)).text;

Funcionó para mí ... espero que funcione para ti también.

Alok Adhao
fuente