Waarom is Event.target geen Element in Typescript?

Ik wil dit gewoon doen met mijn KeyboardEvent

var tag = evt.target.tagName.toLowerCase();

Hoewel Event.targetvan het type EventTargetis, neemt het niet over van Element. Dus ik moet het als volgt casten:

var tag = (<Element>evt.target).tagName.toLowerCase();

Dit komt waarschijnlijk doordat sommige browsers de standaarden niet volgen, toch? Wat is de juiste browseronafhankelijke implementatie in TypeScript?

P.S. Ik gebruik jQuery om het KeyboardEventvast te leggen.


Antwoord 1, autoriteit 100%

Het neemt niet over van Elementomdat niet alle gebeurtenisdoelen elementen zijn.

Van MDN:

Element, document en venster zijn de meest voorkomende gebeurtenisdoelen, maar andere objecten kunnen ook gebeurtenisdoelen zijn, bijvoorbeeld XMLHttpRequest, AudioNode, AudioContext en andere.

Zelfs het KeyboardEventdat u probeert te gebruiken, kan voorkomen op een DOM-element of op het vensterobject (en in theorie op andere dingen), dus daar zou het niet logisch zijn voor evt.targetmoet worden gedefinieerd als een Element.

Als het een gebeurtenis is op een DOM-element, dan zou ik zeggen dat je veilig kunt uitgaan van evt.target. is een Element. Ik denk niet dat dit een kwestie is van cross-browser gedrag. Alleen dat EventTargeteen meer abstracte interface is dan Element.

Meer lezen: https://github.com/Microsoft/TypeScript/issues/29540


Antwoord 2, autoriteit 88%

JLRishe’s antwoord is correct, dus ik gebruik dit gewoon in mijn gebeurtenishandler:

if (event.target instanceof Element) { /*...*/ }

Antwoord 3, autoriteit 82%

Met typescript gebruik ik een aangepaste interface die alleen van toepassing is op mijn functie. Voorbeeld use case.

 handleChange(event: { target: HTMLInputElement; }) {
    this.setState({ value: event.target.value });
  }

In dit geval ontvangt de handleChange een object met een doelveld van het type HTMLInputElement.

Later in mijn code kan ik

. gebruiken

<input type='text' value={this.state.value} onChange={this.handleChange} />

Een schonere benadering zou zijn om de interface in een apart bestand te plaatsen.

interface HandleNameChangeInterface {
  target: HTMLInputElement;
}

gebruik dan later de volgende functiedefinitie:

 handleChange(event: HandleNameChangeInterface) {
    this.setState({ value: event.target.value });
  }

In mijn gebruikssituatie is uitdrukkelijk gedefinieerd dat de enige aanroeper om ChangeChange af te handelen een HTML-elementtype invoertekst is.


Antwoord 4, autoriteit 57%

Typescript 3.2.4

Voor het ophalen van eigendom moet u het doel casten naar het juiste gegevenstype:

e => console.log((e.target as Element).id)

Antwoord 5, autoriteit 16%

Kun je je eigen generieke interface maken die Eventuitbreidt. Zoiets?

interface DOMEvent<T extends EventTarget> extends Event {
  readonly target: T
}

Dan kun je het als volgt gebruiken:

handleChange(event: DOMEvent<HTMLInputElement>) {
  this.setState({ value: event.target.value });
}

Antwoord 6, autoriteit 3%

Met typescript kunnen we type-aliassen gebruiken, zoals:

type KeyboardEvent = {
  target: HTMLInputElement,
  key: string,
};
const onKeyPress = (e: KeyboardEvent) => {
  if ('Enter' === e.key) { // Enter keyboard was pressed!
    submit(e.target.value);
    e.target.value = '';
    return;
  }
  // continue handle onKeyPress input events...
};

Antwoord 7

@Bangonkali geeft het juiste antwoord, maar deze syntaxis lijkt me leesbaarder en gewoon leuker:

eventChange($event: KeyboardEvent): void {
    (<HTMLInputElement>$event.target).value;
}

Antwoord 8

Ik heb meestal met dit probleem te maken als ik te maken heb met gebeurtenissen uit een input-veld, zoals key up. Maar onthoud dat de gebeurtenis overal vandaan kan komen, b.v. van een keyup-luisteraar op document, waar geen bijbehorende valueis. Dus om de informatie correct te verstrekken, zou ik een extra type opgeven:

interface KeyboardEventOnInputField extends KeyboardEvent {
  target: HTMLInputElement;
}
...
  onKeyUp(e: KeyboardEventOnInputField) {
    const inputValue = e.target.value;
    ...
  }

Als de invoer van de functie een type Eventheeft, moet u wellicht met typescript vertellen wat het eigenlijk is:

 onKeyUp(e: Event) {
    const evt = e as KeyboardEventOnInputField;
    const inputValue = evt.target.value;
    this.inputValue.next(inputValue);
  }

Dit is bijvoorbeeld vereist in Angular.


Antwoord 9

Ik gebruik dit:

onClick({ target }: MouseEvent) => {
    const targetDivElement: HTMLDivElement = target as HTMLDivElement;
    const listFullHeight: number = targetDivElement.scrollHeight;
    const listVisibleHeight: number = targetDivElement.offsetHeight;
    const listTopScroll: number = targetDivElement.scrollTop;
    }

Antwoord 10

Voor Angular 10+ gebruikers

Declareer gewoon het HTML-invoerelement en breid het uit om het doel als een object te gebruiken, zoals ik hieronder deed voor mijn bootstrap 4+ bestandsbrowserinvoer. Op deze manier kunt u veel werk besparen.

 selectFile(event: HTMLInputElement & { target: HTMLInputElement}) {
    console.log(event.target.files);
    this.selectedFile = event.target.files[0];
  }

Other episodes