Search code examples
typescriptvuejs3typescript-typingsvue-composition-apitsc

Typescript function arguments type inference issue


I have this piece of code here:

export default function (triggerEl: Ref<HTMLDivElement>, contentEl: Ref<HTMLDivElement>, placement: Ref<Placement> | Placement = 'auto', offset: Ref<number> | number = 0) {

  placement = ref(placement) as Ref<Placement>
  offset = ref(offset)

  const { top: triggerTop, right: triggerRight, bottom: triggerBottom, left: triggerLeft, width: triggerWidth, height: triggerHeight } = useElementBounding(triggerEl)
  const { top: contentTop, right: contentRight, bottom: contentBottom, left: contentLeft, width: contentWidth, height: contentHeight } = useElementBounding(contentEl)


  const position = computed<PopperPosition>(() => {
    let top = Number.MIN_SAFE_INTEGER
    let left = Number.MIN_SAFE_INTEGER

    if (placement.value === 'top') {
      top = triggerTop.value - contentHeight.value - offset.value
      left = triggerLeft.value + triggerWidth.value / 2 - contentWidth.value / 2
    }

    return {
      top,
      left,
    }
  })



  return  null
}

enter image description here

I have converted the 'placement' and 'offset' parameters to their corresponding 'Ref' type, but the below code still thinks they are type Ref | number, so it complains, but they actually never would be number type.

How would I solve the typing check issue here ???


Solution

  • I suppose the source that messes TS's inference is located on lines 21 and 22(reassigning variable values):

    placement = ref(placement) as Ref<Placement>
    offset = ref(offset)
    

    I suggest creating new variables instead, so the final code will look like this:

    export default function (triggerEl: Ref<HTMLDivElement>, contentEl: Ref<HTMLDivElement>, placement: Ref<Placement> | Placement = 'auto', offset: Ref<number> | number = 0) {
    
      const placementRef = ref(placement)
      const offsetRef = ref(offset)
    
      const { top: triggerTop, right: triggerRight, bottom: triggerBottom, left: triggerLeft, width: triggerWidth, height: triggerHeight } = useElementBounding(triggerEl)
      const { top: contentTop, right: contentRight, bottom: contentBottom, left: contentLeft, width: contentWidth, height: contentHeight } = useElementBounding(contentEl)
    
    
      const position = computed<PopperPosition>(() => {
        let top = Number.MIN_SAFE_INTEGER
        let left = Number.MIN_SAFE_INTEGER
    
        if (placementRef.value === 'top') {
          top = triggerTop.value - contentHeight.value - offsetRef.value
          left = triggerLeft.value + triggerWidth.value / 2 - contentWidth.value / 2
        }
    
        return {
          top,
          left,
        }
      })
    
    
    
      return  null
    }