Definitelytyped: React.SyntheticEvent.currentTarget์ด ์•„๋‹Œ T๋ฅผ ํ†ตํ•ด React.SyntheticEvent.target์„ ์ผ๋ฐ˜ํ™”ํ•˜์‹ญ์‹œ์˜ค.

์— ๋งŒ๋“  2016๋…„ 09์›” 26์ผ  ยท  7์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: DefinitelyTyped/DefinitelyTyped

ํ˜„์žฌ React์˜ SyntheticEvent ๋Œ€ํ•œ Typescript 2.0 ์„œ๋ช…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

interface SyntheticEvent<T> {
    currentTarget: EventTarget & T;
    target: EventTarget;
}

์ปค๋ฐ‹ a13fa7abf55daedf25b31258b908548f55962c7a ์— ๋”ฐ๋ฅด๋ฉด target ๋Š” ์›๋ž˜ EventTarget & T ์˜€์ง€๋งŒ์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์ปค๋ฐ‹ 5607f54caffce.fce83bc528f4์—์„œ ๋ณ‘ํ•ฉํ•˜๋Š” ๋™์•ˆ ์‹ค์ˆ˜๋กœ ๋˜๋Œ๋ ค์กŒ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋Š” 2.0 ์ด์ „ ์ฝ”๋“œ(์ƒ์ƒํ•  ์ˆ˜ ์žˆ๋“ฏ์ด React ์ฝ”๋“œ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๊ฐ€๋“ ์ฐจ ์žˆ์Œ)๋ฅผ ๊ฑฐ์˜ ๋˜๋Š” ์ „ํ˜€ ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๋Œ€๋ถ€๋ถ„์˜ ์ฝ”๋“œ๊ฐ€ event.target ์— ์˜์กดํ•˜๋ฏ€๋กœ ์ด๋Š” ์—ฌ์ „ํžˆ pre์— ์˜์กดํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค). event.target ๊ฐ€ ์ œ๋„ค๋ฆญ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— (event.target as any).value ์™€ ๊ฐ™์€ -2.0 ์ฝ”๋“œ.

๊ธฐ๊บผ์ด ํŒจ์น˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์ง€๋งŒ SyntheticEvent.target ์ด ์˜๋„์ ์œผ๋กœ de-generateํ™”๋˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ปดํŒŒ์ผ ํƒ€์ž„์— ๋Œ€์ƒ์˜ ์œ ํ˜•์„ ํ•ญ์ƒ ์•Œ๋ฆด ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ์ผ๋ฐ˜ํ™”ํ•˜๋Š” ๊ฒƒ์€ ๊ฑฐ์˜ ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
target์€ ์ด๋ฒคํŠธ์˜ ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค.
currentTarget์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์š”์†Œ๋กœ, ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋˜๋Š” ๊ธฐํƒ€ ์†์„ฑ์„ ์ฒจ๋ถ€ํ•˜๊ณ  ๋Ÿฐํƒ€์ž„์— ์•ก์„ธ์Šคํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋งค์šฐ ์ฃผ์˜ํ•˜๊ณ  ์ ์ ˆํ•˜๊ฒŒ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

currentTarget ๋Œ€์‹  target์— ์˜์กดํ•˜๋Š” ๊ฒƒ์€ ์ดˆ์‹ฌ์ž์˜ ์‹ค์ˆ˜๋กœ ํ›„์ž๋ณด๋‹ค ๋นจ๋ฆฌ ๋ฌผ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

  handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => {
    e.preventDefault()
    // !!! e.target.dataset is empty if user clicked the <span>, not the <a> !!!
    // !!! how can you type e.target? User might also have clicked the <a> if it has padding !!!
    // you have to use currentTarget, and it is the element that you know the type for sure
    if (e.currentTarget.dataset['closable'] === 'true') {
      this.close()
    }
  }

render() {
  return <a onClick={this.handleTabClick} data-closable="true">
      <span className="fatty">Click me!</span>
   </a>
}

์ด ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

'์ˆ˜์ •'์ด ๋ณ‘ํ•ฉ๋˜๋ฉด e.currentTarget ์ž…๋ ฅํ•  ์ˆ˜ ์—†์œผ๋ฉฐ(์œ ํ˜• ์˜ค๋ฅ˜ ์—†์ด ๋ฐ์ดํ„ฐ ์„ธํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Œ) e.target ๊ฐ€ ์ด์ œ HTMLLinkElement๋กœ ์ž…๋ ฅ๋˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์•ˆ์˜ ์ŠคํŒฌ์„ ํด๋ฆญํ–ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ก ์ ์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ํ™•์‹คํ•  ๋•Œ(์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์ž์‹์ด ์—†๊ฑฐ๋‚˜ ๋ชจ๋‘ ๊ฐ™์€ ์œ ํ˜•์„ ๊ฐ€์ง) SyntheticEvent์— ๋‘ ๋ฒˆ์งธ ์ œ๋„ค๋ฆญ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋Œ€์ƒ์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ€์น˜๊ฐ€ ๊ฑฐ์˜ ์—†์œผ๋ฉฐ ์‹ค์ œ๋กœ ์˜คํ•ด์˜ ์†Œ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์บ์ŠคํŒ…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ํŠน์ • ๊ฒฝ์šฐ์—๋งŒ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค).
ํŠนํžˆ ์ž๋…€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ currentTarget์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  7 ๋Œ“๊ธ€

์ด๊ฒƒ์€ ์•„๋งˆ๋„ ๋ณ‘ํ•ฉ ์ค‘์— ๋ฐœ์ƒํ•œ ์‹ค์ˆ˜์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ™๋ณด ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

#11041, #10784 ๋“ฑ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค. ๋ณ‘ํ•ฉ ํ›„์—๋„ ์ˆ˜์ •๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฏธ์Šคํ„ฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.

์ปดํŒŒ์ผ ํƒ€์ž„์— ๋Œ€์ƒ์˜ ์œ ํ˜•์„ ํ•ญ์ƒ ์•Œ๋ฆด ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ์ผ๋ฐ˜ํ™”ํ•˜๋Š” ๊ฒƒ์€ ๊ฑฐ์˜ ๊ฐ€์น˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
target์€ ์ด๋ฒคํŠธ์˜ ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค.
currentTarget์€ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์š”์†Œ๋กœ, ๋ฐ์ดํ„ฐ ์„ธํŠธ ๋˜๋Š” ๊ธฐํƒ€ ์†์„ฑ์„ ์ฒจ๋ถ€ํ•˜๊ณ  ๋Ÿฐํƒ€์ž„์— ์•ก์„ธ์Šคํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋งค์šฐ ์ฃผ์˜ํ•˜๊ณ  ์ ์ ˆํ•˜๊ฒŒ ์ž…๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

currentTarget ๋Œ€์‹  target์— ์˜์กดํ•˜๋Š” ๊ฒƒ์€ ์ดˆ์‹ฌ์ž์˜ ์‹ค์ˆ˜๋กœ ํ›„์ž๋ณด๋‹ค ๋นจ๋ฆฌ ๋ฌผ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

  handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => {
    e.preventDefault()
    // !!! e.target.dataset is empty if user clicked the <span>, not the <a> !!!
    // !!! how can you type e.target? User might also have clicked the <a> if it has padding !!!
    // you have to use currentTarget, and it is the element that you know the type for sure
    if (e.currentTarget.dataset['closable'] === 'true') {
      this.close()
    }
  }

render() {
  return <a onClick={this.handleTabClick} data-closable="true">
      <span className="fatty">Click me!</span>
   </a>
}

์ด ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

'์ˆ˜์ •'์ด ๋ณ‘ํ•ฉ๋˜๋ฉด e.currentTarget ์ž…๋ ฅํ•  ์ˆ˜ ์—†์œผ๋ฉฐ(์œ ํ˜• ์˜ค๋ฅ˜ ์—†์ด ๋ฐ์ดํ„ฐ ์„ธํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Œ) e.target ๊ฐ€ ์ด์ œ HTMLLinkElement๋กœ ์ž…๋ ฅ๋˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์•ˆ์˜ ์ŠคํŒฌ์„ ํด๋ฆญํ–ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ก ์ ์œผ๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ํ™•์‹คํ•  ๋•Œ(์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์— ์ž์‹์ด ์—†๊ฑฐ๋‚˜ ๋ชจ๋‘ ๊ฐ™์€ ์œ ํ˜•์„ ๊ฐ€์ง) SyntheticEvent์— ๋‘ ๋ฒˆ์งธ ์ œ๋„ค๋ฆญ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋Œ€์ƒ์„ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐ€์น˜๊ฐ€ ๊ฑฐ์˜ ์—†์œผ๋ฉฐ ์‹ค์ œ๋กœ ์˜คํ•ด์˜ ์†Œ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์บ์ŠคํŒ…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ์˜๋ฏธ๊ฐ€ ์žˆ๋Š” ํŠน์ • ๊ฒฝ์šฐ์—๋งŒ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค).
ํŠนํžˆ ์ž๋…€๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ currentTarget์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ DOMAttributes<SomeType> ์—์„œ onClick : MouseEventHandler<SomeType> ๋ฅผ ์–ป์€ ๋‹ค์Œ EventHandler<MouseEvent<SomeType>> ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

    interface EventHandler<E extends SyntheticEvent<any>> {
        (event: E): void;
    }

target์€ currentTarget๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ž…๋ ฅํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. onClick์€ ์ฒ˜๋ฆฌ ์ด๋ฒคํŠธ(currentTarget์ด๋ผ๊ณ ๋„ ํ•จ)๊ฐ€ ์ œ๋„ค๋ฆญ์œผ๋กœ ์žˆ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๊ฒƒ์ด ๋  ์ˆ˜ ์—†์œผ๋ฉฐ ์ปดํŒŒ์ผ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@bbenezech

handleTabClick = (e: React.SyntheticEvent<HTMLLinkElement>) => { ... }

๋Œ€์‹  ๋‹ค์Œ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

handleTabClick = (e: React.FormEvent<HTMLLinkElement>) => { ... }

ClipboardEvent<T> , CompositionEvent<T> , DragEvent<T> , FocusEvent<T> , KeyboardEvent<T> ...
SyntheticEvent๋Š” ๋‚ฎ์€ ์ˆ˜์ค€์˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ @types NPM ์ €์žฅ์†Œ์—์„œ ์—ฌ์ „ํžˆ ์ด์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์–ธ์ œ ๊ฒŒ์‹œ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ

์ด๊ฒƒ์€ ๋‹ค์‹œ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. #12239๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰