[英]Typescript index signature error : Type error: Argument of type is not assignable to parameter of type 'SetStateAction<never[]>'
I'm new to typescript and to Index signatures and I don't find how to solve that error in my code.我是 typescript 和索引签名的新手,我找不到如何解决我的代码中的错误。 I assume that I need to something like on variable sortProperty on the variable sorted, but I can't find the answer.
我假设我需要对变量排序的变量 sortProperty 之类的东西,但我找不到答案。 I have 2 errors.
我有 2 个错误。 One on the setData(sorted)
一个在setData(sorted)
Argument of type { id: number;
类型参数 { id: number; jobName: string;
职位名称:字符串; created: string;
创建:字符串; modified: string;
修改:字符串; }[]' is not assignable to parameter of type 'SetStateAction<never[]>'
}[]' 不可分配给类型为“SetStateAction<never[]>”的参数
and the other on (b[sortProperty])另一个在(b[sortProperty])
Element implicitly has an 'any' type because expression of type 'string' can't be used to index
元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引
data.js数据.js
export const tasks = [
{
id: "1",
jobName: 'MK-00544 • Spacecraft',
created: '2016-09-03',
modified: '2016-09-04'
},
{
id: "2",
jobName: 'MK-00545 • Spacecraft',
created: '2017-09-26',
modified: '2018-09-29'
},
{
id: "3",
jobName: 'MK-00546 • Spacecraft',
created: '2019-10-03',
modified: '2022-12-08'
},
{
id: "4",
jobName: 'MK-00547 • Spacecraft',
created: '2020-09-12',
modified: '2021-09-03'
},
{
id: "5",
jobName: 'MK-005478 • Spacecraft',
created: '2019-09-03',
modified: '2019-09-03'
},
{
id: "6",
jobName: 'MK-00549 • Spacecraft',
created: '2019-09-03',
modified: '2019-09-03'
}
]
Job.tsx:作业.tsx:
interface Task {
[key: string]: string
}
const [data, setData] = useState<Task>([])
const [sortType, setSortType] = useState('jobName')
useEffect(() => {
const sortArray = (type: string) => {
interface StringIndexedObject {
[key: string]: string
}
const types: StringIndexedObject = {
jobName: 'jobName',
created: 'created',
modified: 'modified'
}
interface AnotherStringIndexedObject {
[key: string]: keyof Task
}
const sortProperty = types[type]
const sorted: AnotherStringIndexedObject = [...tasks].sort(
(a, b) => new Date(b[sortProperty]) - new Date(a[sortProperty])
)
console.log(sorted)
setData(sorted)
}
sortArray(sortType)
}, [sortType])
return (
<div className="font-bold">Sort by:</div>
<select
onChange={(e) => setSortType(e.target.value)}
className="text-center px-5 bg-gray-200 rounded-xl"
>
<option value="id">Id</option>
<option value="jobName">Job name</option>
<option value="created">Newest</option>
<option value="modified">Last modified</option>
</select>
<div>({tasks.length} users)</div>
{data.map((task) => (
<tr
key={task.id}
className="tableau text-center cursor-pointer"
onClick={() => router.push(`/job/${task.id}`)}
>
<td className="py-3">{task.jobName}</td>
<td className="py-3">
<div className="flex items-center gap-5 justify-center">
{task.created}
</div>
</td>
<td className="py-3">
<div className="flex items-center gap-5 justify-center">
{task.modified}
</div>
</td>
))}
You've got a bunch of issues here which are all related.你在这里遇到了一堆问题,这些问题都是相关的。 When the type for one variable is incomplete or incorrect it can cause issues in other places where you use that variable.
当一个变量的类型不完整或不正确时,它可能会导致您使用该变量的其他地方出现问题。
Your component's job is to sort and render an array of task objects.您的组件的工作是排序和呈现一组任务对象。 It internally stores two states:
它内部存储两种状态:
(Note: the sorted array one doesn't need to be a state as it is a derived value. Personally I would use a useMemo
instead of a useState
and a useEffect
but what you have will work so let's keep it and focus on the TypeScript issues) (注意:排序后的数组不需要是 state,因为它是派生值。就我个人而言,我会使用
useMemo
而不是useState
和useEffect
,但你所拥有的将起作用,所以让我们保留它并专注于 TypeScript问题)
Here are the things that I've fixed:以下是我已修复的问题:
1. Describe the type of a task object. 1.描述任务类型object。
Not every string is a valid key here.并非每个字符串都是此处的有效键。 We have a few known properties and that's it.
我们有一些已知的属性,仅此而已。
interface Task {
id: string;
jobName: string;
created: string;
modified: string;
}
2. Set a type for the data
state. 2.为
data
state设置类型。
It is an array of tasks aka Task[]
.它是一组任务,又名
Task[]
。 You need a type here because the initial value is an empty array which has type never[]
.您在这里需要一个类型,因为初始值是一个类型为
never[]
的空数组。 If the initial array was not empty then it could be inferred automatically.如果初始数组不为空,则可以自动推断。
const [data, setData] = useState<Task[]>([])
3. Defined your types
object as mapping from string
to keyof Task
. 3. 将
types
object 定义为从string
到keyof Task
的映射。
Now the sortProperty
has the type keyof Task
, meaning that it is always a property of the Task
.现在
sortProperty
的类型为keyof Task
,这意味着它始终是Task
的属性。
const sortArray = (type: string) => {
interface StringIndexedObject {
[key: string]: keyof Task
}
const types: StringIndexedObject = {
jobName: 'jobName',
created: 'created',
modified: 'modified'
}
const sortProperty = types[type];
You can also do:你也可以这样做:
const types: Record<string, keyof Task> = {
4. Removed the AnotherStringIndexedObject
type. 4. 删除了
AnotherStringIndexedObject
类型。
The sorted array is not an object. It is an array Task[]
.排序后的数组不是 object。它是一个数组
Task[]
。 You can write const sorted: Task[]
, but you don't need to.您可以编写
const sorted: Task[]
,但您不需要。
5. Removed the new Date
handling. 5.删除了
new Date
处理。
This doesn't make sense if the sort type is 'jobName'
or 'id'
.如果排序类型是
'jobName'
或'id'
则这没有意义。 What is new Date('MK-005478 • Spacecraft')
?什么是
new Date('MK-005478 • Spacecraft')
? For the fields which are dates, we can compare the ISO strings as strings.对于日期字段,我们可以将 ISO 字符串作为字符串进行比较。
6. Used lodash sortBy
for the sorting. 6. 使用lodash
sortBy
进行排序。
You can define a custom compare function but I find this really annoying.您可以定义一个自定义比较 function但我觉得这真的很烦人。
const sorted = sortBy(tasks, sortProperty);
7. Renamed your data file from data.js
to data.ts
7. 将数据文件从
data.js
重命名为data.ts
If it is a TypeScript file then your imported tasks
variable will have proper types based on its values.如果它是一个 TypeScript 文件,那么您导入的
tasks
变量将根据其值具有适当的类型。
Job.tsx作业.tsx
import React, { useState, useEffect } from 'react';
import { sortBy } from 'lodash';
import { useRouter } from 'next/router';
import { tasks } from './data';
export interface Task {
id: string;
jobName: string;
created: string;
modified: string;
}
export const Job = () => {
const router = useRouter();
const [data, setData] = useState<Task[]>([])
const [sortType, setSortType] = useState('jobName')
useEffect(() => {
const sortArray = (type: string) => {
interface StringIndexedObject {
[key: string]: keyof Task
}
const types: StringIndexedObject = {
jobName: 'jobName',
created: 'created',
modified: 'modified'
}
const sortProperty = types[type];
const sorted = sortBy(tasks, sortProperty);
console.log(sorted)
setData(sorted)
}
sortArray(sortType)
}, [sortType]);
return (
<div>
<div className="font-bold">Sort by:</div>
<select
onChange={(e) => setSortType(e.target.value)}
className="text-center px-5 bg-gray-200 rounded-xl"
>
<option value="id">Id</option>
<option value="jobName">Job name</option>
<option value="created">Newest</option>
<option value="modified">Last modified</option>
</select>
<div>({tasks.length} users)</div>
{data.map((task) => (
<tr
key={task.id}
className="tableau text-center cursor-pointer"
onClick={() => router.push(`/job/${task.id}`)}
>
<td className="py-3">{task.jobName}</td>
<td className="py-3">
<div className="flex items-center gap-5 justify-center">
{task.created}
</div>
</td>
<td className="py-3">
<div className="flex items-center gap-5 justify-center">
{task.modified}
</div>
</td>
</tr>
))}
</div>
)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.