开发者问题收集

当使用 ref 时,哪个重载会匹配调用?

2021-08-14
541

我在以下代码中遇到了一个我无法理解的 TS 错误:

<script lang="ts">

import {defineComponent, computed, toRef} from 'vue'
import _ from 'lodash'
import {DateTime} from 'luxon'

interface CalendarEvent {
  start: string
  end: string
  name: string
  id: string
  important: boolean
}

function emptyCalendarEvent(): CalendarEvent[] {
  return [{
    start: '',
    end: '',
    name: '',
    id: '',
    important: false
  }]
}

export default defineComponent({
  name: 'GoogleCalendar',
  props: {
    when: {type: String, default: ''},
    data: {type: Array, default: () => emptyCalendarEvent()},
  },
  setup(props) {

    let allEvents = toRef(props, 'data')
    let importantEvents = computed(() => (allEvents.value.filter((x: CalendarEvent) => x.important)))

(...)

最后一行的完整错误是

<html>TS2769: No overload matches this call.<br/>Overload 1 of 2, '(predicate: (value: unknown, index: number, array: unknown[]) =&gt; value is unknown, thisArg?: any): unknown[]', gave the following error.<br/>Argument of type '(x: CalendarEvent) =&gt; boolean' is not assignable to parameter of type '(value: unknown, index: number, array: unknown[]) =&gt; value is unknown'.<br/>Types of parameters 'x' and 'value' are incompatible.<br/>Type 'unknown' is not assignable to type 'CalendarEvent'.<br/>Overload 2 of 2, '(predicate: (value: unknown, index: number, array: unknown[]) =&gt; unknown, thisArg?: any): unknown[]', gave the following error.<br/>Argument of type '(x: CalendarEvent) =&gt; boolean' is not assignable to parameter of type '(value: unknown, index: number, array: unknown[]) =&gt; unknown'.<br/>Types of parameters 'x' and 'value' are incompatible.<br/>Type 'unknown' is not assignable to type 'CalendarEvent'.

控制台中提供了更易读的版本:

TS2769: No overload matches this call.
  Overload 1 of 2, '(predicate: (value: unknown, index: number, array: unknown[]) => value is unknown, thisArg?: any): unknown[]', gave the following error.
    Argument of type '(x: CalendarEvent) => boolean' is not assignable to parameter of type '(value: unknown, index: number, array: unknown[]) => value is unknown'.
      Types of parameters 'x' and 'value' are incompatible.
        Type 'unknown' is not assignable to type 'CalendarEvent'.
  Overload 2 of 2, '(predicate: (value: unknown, index: number, array: unknown[]) => unknown, thisArg?: any): unknown[]', gave the following error.
    Argument of type '(x: CalendarEvent) => boolean' is not assignable to parameter of type '(value: unknown, index: number, array: unknown[]) => unknown'.
      Types of parameters 'x' and 'value' are incompatible.
        Type 'unknown' is not assignable to type 'CalendarEvent'.
    61 |     let allEvents = toRef(props, 'data')
    62 |     // let importantEvents = computed(() => filteredEvents.value.filter((x: CalendarEvent) => x.important))
  > 63 |     let importantEvents = computed(() => (allEvents.value.filter((x: CalendarEvent) => x.important)))
       |                                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    64 |
    65 |     function extractTime(what: string) {
    66 |       return DateTime.fromISO(what).toFormat('H:mm')

好吧, 可读 在我的例子中是一种夸大其词 - 有人能好心地向我解释一下这个错误到底是什么意思吗?

我读了一些其他答案,这通常意味着函数的参数数量错误。然而,我认为,在我的情况下,这更多地与 Vue3 ref 概念有关(胡乱猜测)

2个回答

默认情况下, toRef(...) 的返回类型为 Ref<unknown[]> ,可转换为 Ref<CalendarEvent[]> :

import {defineComponent, computed, toRef,Ref} from 'vue'
                                       //🔺 import the type Ref
....
  setup(props) {

    let allEvents  = toRef(props,'data') as Ref<CalendarEvent[]>

   let importantEvents = computed(() => (allEvents.value.filter((x) => x.important)))
                                                              //🔺 the right type is inferred here 

Boussadjra Brahim
2021-08-14

无法自动推断 Array props 的类型,因此 props.data 解析为 unknown[] 类型。

要明确输入数组,请 使用类型断言 PropType<YourArrayType> type 属性设置为 Array 来声明 prop:

import { PropType } from 'vue'

export default defineComponent({
  props: {
    data: {               👇
      type: Array as PropType<CalendarEvent[]>,
      default: () => emptyCalendarEvent()
    },
  },
}

这使 TypeScript 能够从 toRef(props, 'data') 推断出正确的类型。

tony19
2021-08-14