我有一个Vue3/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是其中的一种.

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>

推荐答案

您正在将一个函数作为key传入

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

TypeScrip告诉你key必须是string | number | symbol | undefined.

我认为您希望执行该函数,而不是传递它:

:key="hourAtDefaultCity.toUnixInteger()"

Typescript相关问答推荐

具有映射返回类型的通用设置实用程序

React组件数组及其props 的类型定义

为什么ESLint抱怨通用对象类型?

在Typescribe中,extends工作,但当指定派生给super时出错""

如何缩小变量访问的对象属性范围?

我想创建一个只需要一个未定义属性的打字脚本类型

如何在TypeScrip中正确键入元素和事件目标?

TypeScrip省略了类型参数,仅当传递另一个前面的类型参数时才采用默认类型

是否可以针对联合类型验证类型属性名称?

在Reaction-Native-ReAnimated中不存在Animated.Value

如果数组使用Reaction-Hook-Form更改,则重新呈现表单

如何在使用条件类型时使用void

我在Angular 17中的environment.ts文件中得到了一个属性端点错误

如何避免从引用<;字符串&>到引用<;字符串|未定义&>;的不安全赋值?

打字脚本错误:`不扩展[Type]`,而不是直接使用`[Type]`

可以将JS文件放在tsconfig';s includes/files属性?或者,我如何让tsc判断TS项目中的JS文件?

如何填写Partial的一些属性并让类型系统知道它?

定义一个只允许来自另一个类型的特定字符串文字的类型的最佳方式

const 使用条件类型时,通用类型参数不会推断为 const

为什么我们在条件语句中使用方括号[]?