typescript 如何在Vue动态类的上下文中解释错误TS2345?

xdyibdwo  于 2023-10-22  发布在  TypeScript
关注(0)|答案(1)|浏览(174)

我有一个Vue 3/Vite/TS应用程序,在npm run dev中运行时运行良好,但由于错误TS2345而无法构建。我知道这是一个与打字有关的错误,但我无法理解错误到底在哪里。

transforming (15) node_modules\@vue\reactivity\dist\reactivity.esm-bundler.src/TimesView.vue:15:18 - error TS2345: Argument of type '{ key: () => number; id: string; class: string; }' is not assignable to parameter of type 'HTMLAttributes & ReservedProps & Record<string, unknown>'.
  Type '{ key: () => number; id: string; class: string; }' is not assignable to type 'ReservedProps'.
    Types of property 'key' are incompatible.
      Type '() => number' is not assignable to type 'string | number | symbol | undefined'.

15                 
<div 
v-for="hourAtDefaultCity in [...Array(24).keys()].map(x => locTime(x, city.timezone))" 
:key="hourAtDefaultCity.toUnixInteger" 
id="hour" 
class="flex justify-center place-content-between text-xl grow" 
:class="{ 'bg-gray-300 text-gray-400': isNightLocallyForHourAtDefaultCity(hourAtDefaultCity.hour, city.timezone), 'bg-sky-100 text-sky-900': !isNightLocallyForHourAtDefaultCity(hourAtDefaultCity.hour, city.timezone) }"
>

从堆栈底部开始,我了解到错误实际上是关于() => number(因此,函数的返回值应该是number)的,该错误不能分配给一组类型的字符串|number|符号|未定义'。这是我不明白的:number就是其中之一。
isNightLocallyForHourAtDefaultCity的声明如下:

const locTime = (hour: number, timezone: string): DateTime => DateTime.fromISO(`${hour.toString().padStart(2, '0')}:00`, { zone: defaultTimezone.value }).setZone(timezone)
const isNightLocallyForHourAtDefaultCity = (hour: number, timezone: string): boolean => locTime(hour, timezone).hour < config.value.dayStartHour || locTime(hour, timezone).hour > config.value.dayEndHour

我在哪里会有() => number TS抱怨?
编辑:为了安全起见,下面是组件的完整代码(包括TS不抱怨的部分,当然还有我上面提到的所有内容)

<template>
    <div class="flex justify-center h-screen">
        <div class="flex flex-row" id="cities">
            <div v-for="city in config.cities" :key="city.name" class="flex flex-col shrink-0 justify-between">
                <div class="cityName items-center mb-3 flex flex-col" :class="{ 'bg-green-200': city.name === config.defaultCity }">
                    <div class="text-center font-extrabold text-4xl" :style="maxCityNameSizeStyle" ref="maxCityNameSizeRefs">
                        {{ city.name }}
                    </div>
                    <div class="">
                        {{ now.setZone(city.timezone).toFormat('HH:mm') }}
                    </div>
                </div>
                <!-- iterate over the column of hours of the default city, adapting the dispayed to the city tz -->
                <div v-for="hourAtDefaultCity in [...Array(24).keys()].map(x => locTime(x, city.timezone))" :key="hourAtDefaultCity.toUnixInteger" id="hour" class="flex justify-center place-content-between text-xl grow" :class="{ 'bg-gray-300 text-gray-400': isNightLocallyForHourAtDefaultCity(hourAtDefaultCity.hour, city.timezone), 'bg-sky-100 text-sky-900': !isNightLocallyForHourAtDefaultCity(hourAtDefaultCity.hour, city.timezone) }">
                    <span>⸺</span>
                    <span class="font-bold">{{ hourAtDefaultCity.toFormat('HH') }}</span>
                    <span>:</span>
                    <span>{{ hourAtDefaultCity.toFormat('mm') }}</span>
                    <span>⸺</span>
                </div>
            </div>
        </div>

        <time-bar :now="now" :config="config" :maxCityNameSize="maxCityNameSize" :defaultTimezone="defaultTimezone"></time-bar>
    </div>
</template>

<script setup lang="ts">
import { DateTime } from "luxon";
import { onMounted, ref, watch } from 'vue'
import TimeBar from './TimeBar.vue'
import { config } from "./config";

const props = defineProps({
    defaultTimezone: {
        type: String,
        default: 'Etc/UTC'
    }
})
const defaultTimezone = ref(props.defaultTimezone)

// global current time, updated every X seconds
const now = ref(DateTime.now())
// setInterval(() => (now.value = DateTime.now()), 1000)

// compute the time to display based on the hour number of the other ones
const locTime = (hour: number, timezone: string): DateTime => DateTime.fromISO(`${hour.toString().padStart(2, '0')}:00`, { zone: defaultTimezone.value }).setZone(timezone)
const isNightLocallyForHourAtDefaultCity = (hour: number, timezone: string): boolean => locTime(hour, timezone).hour < config.value.dayStartHour || locTime(hour, timezone).hour > config.value.dayEndHour

const maxCityNameSize = ref(0)
const maxCityNameSizeStyle = ref('')

watch(() => config.value, () => console.log(`config in times view changed: ${JSON.stringify(config.value)}`))

onMounted(() => {
    // style for the width of the column
    maxCityNameSize.value = Math.max(...Array.from(document.querySelectorAll('.cityName')).map((x) => x.clientWidth))
    maxCityNameSizeStyle.value = `width: ${maxCityNameSize.value}px`

    // location.href = 'http://localhost:5173/?cities=San_Diego,America/Los_Angeles;Paris,Europe/Paris;Boston,America/New_York;Pune,Asia/Kolkata;Tokyo,Asia/Tokyo;UTC,Etc/UTC&default=UTC'
})
</script>
irtuqstp

irtuqstp1#

你正在传入一个函数key

<div
  v-for="..."
  :key="hourAtDefaultCity.toUnixInteger"
  ...

Typescript告诉你key必须是string | number | symbol | undefined
我认为你想执行函数而不是传递它:

:key="hourAtDefaultCity.toUnixInteger()"

相关问题