'use client'
import { useState } from 'react'
import { ArrowDownIcon } from '@heroicons/react/24/outline'
interface FilterGroupProps<T extends string[] | number[]> {
title: string
options: T // Options type depends on the value of dataType
emitClick: (category: Record<string, T>) => void
}
const FilteringGroup = <T extends string[] | number[]>({
title,
options,
emitClick,
}: FilterGroupProps<T>) => {
const [isOpen, setIsOpen] = useState(true)
const [checkedValues, setCheckedValues] = useState([])
const toggle = (val: string | number) => {
let newValues = [...checkedValues]
if (!checkedValues.includes(val)) {
newValues = [...checkedValues, val]
} else {
newValues = newValues.filter((x) => x !== val)
}
setCheckedValues(newValues)
}
return (
<div className="m">
{options.map((o, oi) => (
<label key={`${o}_${oi}`} className="peer text-sm">
<input
type="checkbox"
name="todo[1]"
checked={checkedValues.includes(o)}
onChange={() => toggle(o)}
/>
{o}
</label>
))}
</div>
)
}
export default FilteringGroup
选项示例:
我是打字稿新手,我正在处理 useState 的动态数组。
该子组件将从其父组件接收一个
options
属性,格式为 pure string[]
或 pure number[]
。一切都工作正常,直到我想将 toggle
事件作为过滤器函数进行处理。
这行
if (!checkedValues.includes(val))
向我显示了错误
Argument of type 'string | number' is not assignable to parameter of type 'never'.
Type 'string' is not assignable to type 'never'.
我理解初始空 [] 导致的错误,因为过滤器列表中还没有任何内容,但是我们如何根据
checkValues
类型自动初始化 x
的类型?假设如果 x
是一个字符串,那么 checkValues
应该是 string[]
,否则是 number[]
。
或者我是否可以将
checkValues
设置为使用动态泛型类型?
3天后找不到解决方案...
将通用
T
更改为 T extends string | number
:
interface FilterGroupProps<T extends string | number> {
title: string
options: T[] // Options type depends on the value of dataType
emitClick: (category: Record<string, T>) => void
}
现在,每当您需要键入基于
T
的值时,请使用 options
:
const FilteringGroup = <T extends string | number>({
title,
options,
emitClick,
}: FilterGroupProps<T>) => {
const [isOpen, setIsOpen] = useState(true)
const [checkedValues, setCheckedValues] = useState<T[]>([]) // <- array of T values
// single T value
const toggle = (val: T) => {
let newValues = [...checkedValues]
if (!checkedValues.includes(val)) {
newValues = [...checkedValues, val]
} else {
newValues = newValues.filter((x) => x !== val)
}
setCheckedValues(newValues)
}