Event.target이 Typescript의 요소가 아닌 이유는 무엇입니까?


115

내 KeyboardEvent로이 작업을 수행하고 싶습니다.

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

Event.target은 EventTarget 유형이지만 Element에서 상속하지 않습니다. 그래서 다음과 같이 캐스팅해야합니다.

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

이것은 아마도 표준을 따르지 않는 일부 브라우저 때문일 것입니다. TypeScript에서 올바른 브라우저 불가지론 적 구현은 무엇입니까?

추신 : 저는 jQuery를 사용하여 KeyboardEvent를 캡처하고 있습니다.


7
비트 청소기 구문var element = ev.target as HTMLElement
아드리안 Moisa

답변:


57

상속되지 않습니다 Element모든 이벤트 대상이 요소가 아니기 때문에 .

MDN에서 :

요소, 문서 및 창은 가장 일반적인 이벤트 대상이지만 다른 개체도 이벤트 대상이 될 수 있습니다 (예 : XMLHttpRequest, AudioNode, AudioContext 등).

KeyboardEvent사용하려는 것 조차도 DOM 요소 또는 창 객체 (그리고 이론적으로는 다른 것들)에서 발생할 수 있습니다. 따라서 바로 거기에서 evt.target다음과 같이 정의하는 것은 의미가 없습니다 .Element .

DOM 요소에 대한 이벤트 인 경우 안전하게 가정 할 수 있습니다 evt.target. 입니다 Element. 나는 이것이 브라우저 간 동작의 문제라고 생각하지 않습니다. 그것은 단지 EventTarget더 추상적 인 인터페이스입니다.Element .

추가 정보 : https://typescript.codeplex.com/discussions/432211


8
이 경우 KeyboardEvent 및 MouseEvent에는 항상 연관된 요소를 포함하는 EventTarget과 동일한 자체가 있어야합니다. DOM은 ... 너무 맛없어입니다 : /
daniel.sedlacek

7
나는 DOM이나 TypeScript에 대한 전문가는 아니지만 EventTarget의 디자인이 너무 모호하고 TypeScript와 관련이 없다고 말할 것입니다.
daniel.sedlacek

2
@ daniel.sedlacek 한편, KeyboardEvent들 때문에 거기가 제공하는 것은 불가능하다, (이론적으로는 다른 일을하고) 모두 DOM 요소와 윈도우 객체에 발생할 수있는 KeyboardEvent.target것보다 더 이상 특정의 종류를 EventTarget생각하지 않는, KeyboardEvent또한이어야한다 제네릭 유형 KeyboardEvent<T extends EventTarget>이며 KeyboardEvent<Element>코드 전체 에 모든 것을 넣을 수 있습니다. 그 시점에서, 당신은 고통 스럽지만 명시적인 캐스트를하는 것이 낫습니다.
JLRishe 2015 년

14
나중에 다른 사람에게 도움이되는 경우 태그 value속성에 액세스하기 위해 특정 요소 유형으로 캐스팅해야했습니다 <select>. 예let target = <HTMLSelectElement> evt.target;
munsellj jul.

1
@munsellj (불행히도) 형식화 된 환경에서 모호성을 처리하는 올바른 방법입니다.
pilau

47

typescript를 사용하여 내 기능에만 적용되는 사용자 정의 인터페이스를 사용합니다. 사용 사례의 예.

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

이 경우 handleChange는 HTMLInputElement 유형의 대상 필드가있는 오브젝트를 수신합니다.

나중에 내 코드에서 사용할 수 있습니다.

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

더 깔끔한 접근 방식은 인터페이스를 별도의 파일에 배치하는 것입니다.

interface HandleNameChangeInterface {
  target: HTMLInputElement;
}

나중에 다음 함수 정의를 사용하십시오.

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

내 사용 사례에서 handleChange의 유일한 호출자는 입력 텍스트의 HTML 요소 유형이라는 것이 명시 적으로 정의되어 있습니다.


이것은 나를 위해 완벽하게 작동했습니다. 모든 종류의 불쾌감을 시도하고 EventTarget을 확장했습니다. 그러나 이것은 가장 깨끗한 솔루션입니다. +1
Kitson

1
여기에 추가하기 위해 이벤트 정의를 확장해야하는 경우 다음과 같이 할 수 있습니다.handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement> & { target: HTMLInputElement }) => {...}
Kitson

40

JLRishe의 대답이 정확하므로 이벤트 처리기에서 간단히 사용합니다.

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

28

타이프 스크립트 3.2.4

속성을 검색하려면 대상을 적절한 데이터 유형으로 캐스팅해야합니다.

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

<HTMLInputElement>event.target;구문 과 동일 합니까?
Konrad Viltersten

@KonradViltersten, 그들은 똑같은 일을합니다. as가 JSX과 충돌하기 때문에 구문이 도입되었다. as일관성 을 위해 사용 하는 것이 좋습니다 . basarat.gitbooks.io/typescript/docs/types/type-assertion.html
Adam

아하, 알겠습니다. 또한 팀의 백엔드 경험에 따라 많은 경우 이점이되는 C # '이 더 많이 나타납니다. 구문이 뭔가 닮았지만 기술적으로는 완전히 다른 것을 암시하는 거짓 친구 중 하나가 아니라면. (나는 Angular와 C # 사이에 varconst를 생각하고 있는데 , 내 슬픈 경험, hehe).
Konrad Viltersten

2

.NET을 확장하는 고유 한 일반 인터페이스를 만들 수 있습니까 Event? 이 같은?

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

그런 다음 다음과 같이 사용할 수 있습니다.

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

1

typescript를 사용하면 다음과 같이 유형 별칭을 활용할 수 있습니다.

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

0

@Bangonkali가 정답을 제공하지만이 구문은 더 읽기 쉽고 나에게 더 좋습니다.

eventChange($event: KeyboardEvent): void {
    (<HTMLInputElement>$event.target).value;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.