簡體   English   中英

這是對 typescript 的良好轉換嗎? 為什么會出現這個錯誤?

[英]Is this a good conversion to typescript? Why this error?

我有這段代碼可以在需要時調整 textarea 元素的大小:

function resize({ target }) {
  target.style.height = '1px'
  target.style.height = +target.scrollHeight + 'px'
}

export function textareaResize(el) {
  resize({ target: el })
  el.style.overflow = 'hidden'
  el.addEventListener('input', resize)
  return {
    destroy: () => el.removeEventListener('input', resize)
  }
}

我正在嘗試將此代碼轉換為 Typescript 為:

function resize(event: Event) {
  const target = event.target as HTMLTextAreaElement
  target.style.height = '1px'
  target.style.height = `${+target.scrollHeight}px`
}

export function textareaResize(el: HTMLTextAreaElement): { destroy: () => void} {
  resize({ target: el })
  el.style.overflow = 'hidden'
  el.addEventListener('input', resize)
  return {
    destroy: () => el.removeEventListener('input', resize)
  }
}

但是我在resize({ target: el })行顯然有這個錯誤:

Argument of type '{ target: HTMLTextAreaElement; }' is not assignable to parameter of type 'Event'.
  Type '{ target: HTMLTextAreaElement; }' is missing the following properties from type 'Event': bubbles, cancelBubble, cancelable, composed, and 17 more.ts(2345)

我該如何解決?

也許我用錯了把它改成這樣: function resizeTextArea(event: Event) ,對吧?

第一個問題是:當resizeTextArea只使用其中的target時,為什么需要一個Event 我天真的第一次重構是:

function resizeTextArea(target: HTMLTextAreaElement) {
  target.style.height = '1px'
  target.style.height = `${+target.scrollHeight}px`
}

export function textareaResize(element: HTMLTextAreaElement): { destroy: () => void} {
  resizeTextArea(element)
  element.style.overflow = 'hidden'
  element.addEventListener('input', (e: Event) => resizeTextArea(e.target as HTMLTextAreaElement))
  return {
    destroy: () => element.removeEventListener('input', (e: Event) => resizeTextArea(e.target as HTMLTextAreaElement))
  }
}

如果您出於某種原因想堅持使用Event ,可以將{target}轉換為Event

function resizeTextArea(event: Event) {
  const target = event.target;
  target.style.height = '1px'
  target.style.height = `${+target.scrollHeight}px`
}

export function textareaResize({ target }: HTMLTextAreaElement): { destroy: () => void} {
  resizeTextArea({ target } as Event)
  element.style.overflow = 'hidden'
  element.addEventListener('input', resizeTextArea)
  return {
    destroy: () => element.removeEventListener('input', (e: Event) => resizeTextArea)
  }
}

請注意,這不是最安全的方法,因為您實際上是在textareaResize中構造一個不完整的Event ,這會在resizeTextArea中創建一個隱含且難以理解的合同:在該 function 工作的人需要知道該event是,在事實上,不是一個完整的Event ,而只是一個具有target屬性的 object 。

普通的 object 不是事件:

resizeTextArea({ target: element })

沒有將 Event 傳遞給resizeTextArea ,因此 TS 失敗。

一種選擇是改用this ,輸入HTMLTextAreaElement

function resizeTextArea(this: HTMLTextAreaElement) {
  this.style.height = '1px'
  this.style.height = `${+this.scrollHeight}px`
}

export function textareaResize(element: HTMLTextAreaElement): { destroy: () => void} {
  resizeTextArea.call(element)
  element.style.overflow = 'hidden'
  element.addEventListener('input', resizeTextArea)
  return {
    destroy: () => element.removeEventListener('input', resizeTextArea)
  }
}

(如果你也需要事件參數,你可以做function resizeTextArea(this: HTMLTextAreaElement, event?: Event) { )

您正在嘗試將 HTMLTextAreaElement 類型的目標傳遞給具有 Event 類型參數的 function。 嘗試這個:

function resize(target: HTMLTextAreaElement) {
  target.style.height = '1px'
  target.style.height = `${+target.scrollHeight}px`
}

export function textareaResize(el: HTMLTextAreaElement): { destroy: () => void} {
  resize({ target: el })
  el.style.overflow = 'hidden'
  el.addEventListener('input', resize)
  return {
    destroy: () => el.removeEventListener('input', (event: Event) => resize( event.target as HTMLTextAreaElement ))
  }
}

類型系統是用來保護你的……不要試圖“投射”你的方式只是為了讓代碼編譯。 錯誤消息告訴您,此 object 不支持超過 20 項預期的“事件”。 而且,很明顯,“HTML 文本區域元素”不是“事件”,也永遠不會是。 不幸的是,你一開始沒有告訴我們你為什么要這么做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM