如何正确使用 TypeScript 和 Array.prototype.reduce?
Posted
技术标签:
【中文标题】如何正确使用 TypeScript 和 Array.prototype.reduce?【英文标题】:How to use TypeScript with Array.prototype.reduce correct? 【发布时间】:2022-01-10 23:26:10 【问题描述】:我有以下reduce
函数,我尝试的任何方法都没有消除错误:
interface ITask
id: string;
was: string;
//sampleData:
const tasks = [
id: "a", was: "Foo",
id: "b", was: "Foo",
id: "c", was: "Bad"
];
const uniqueList = tasks.reduce<>((acc, current) =>
const x = acc.find((item: ITask) => item.was === current.was);
return !x ? acc.concat(current) : acc;
, []);
这给了我:
Property 'find' does not exist on type 'never'.
Property 'was' does not exist on type 'never'.
Property 'concat' does not exist on type 'never'.
current
的值是 ITask
类型,accumulator
的类型是 ITask[]|[]
,这对我来说是绝对合乎逻辑的。因此,我尝试了:
const uniqueList = tasks.reduce<>((acc: ITask[] | [], current: ITask) =>
const x = acc.find((item: ITask) => item.was === current.was);
return !x ? acc.concat(current) : acc;
, []);
这给出了:
Argument of type '(acc: ITask[] | [], current: ITask) => ITask[]' is not assignable to parameter of type '(previousValue: never, currentValue: never, currentIndex: number, array: never[]) => never'.
Type 'ITask[]' is not assignable to type 'never'.
Argument of type 'ITask' is not assignable to parameter of type 'ConcatArray<never>'.
Type 'ITask' is missing the following properties from type 'ConcatArray<never>': length, join, slice
编辑:
来自我尝试过的评论:
const uniqueList = tasks.reduce((acc, current: ITask) =>
const x = acc.find((item: ITask) => item.was === current.was);
return !x ? acc.concat(current) : acc;
, [] as ITask[] | []);
这给了我:
Property 'find' does not exist on type 'never'.
Property 'concat' does not exist on type 'never'.
【问题讨论】:
相信答案就在这里:***.com/questions/54117100/… 你只需要输入累加器..., [] as ITask[]);
或tasks.reduce<ITask[]>(...
playground
这能回答你的问题吗? give type to accumulator with array reduce typescript
为什么是有条件的?它应该只是useState<ITask[]>
,除非您打算在其中存储其他东西?
任何空数组仍然有一个类型。该类型表示只有该类型的元素才能添加到数组中,而不管它是否包含元素。这是一个 codesandox 显示 React 中的类型。
【参考方案1】:
使用更多类型指示器。看到这个stackblitz snippet。
const tasks: ITask[] = [
// ^ note: typo in question
id: "a", was: "Foo",
id: "b", was: "Foo",
id: "c", was: "Bad",
];
const uniqueList: ITask[] = tasks.reduce<ITask[]>((acc: ITask[], current: ITask) =>
const x = acc.find((item: ITask) => item.was === current.was);
return !x ? acc.concat(current) : acc;
, []);
【讨论】:
这给了我Expected 0 type arguments, but got 1
for <ITask[]>
。
我想将: ITask[]
添加到uniqueList
。查看编辑后的答案
当我删除 | []
时,即使没有 <ITask[]>
,它也可以正常工作【参考方案2】:
这里是一个在 React 组件中使用 useState
的示例,仅供参考。
TS Playground
export interface ITask
id: string;
was: string;
const tasks: ITask[] = [
id: "a", was: "Foo",
id: "b", was: "Foo",
id: "c", was: "Bad"
];
// 'tasks' is typed by useState
//const [tasks, setTasks] = useState<ITask[]>([]);
const uniqueList = tasks.reduce<ITask[]>((acc, current) =>
const x = acc.find((item: ITask) => item.was === current.was);
return !x ? acc.concat(current) : acc;
, []);
查看完整的codesandbox。
import useEffect, useState from "react";
export interface ITask
id: string;
was: string;
interface IProps
[tasks: string]: ITask[];
export default function App( tasks: _tasks : IProps)
const [tasks, setTasks] = useState<ITask[]>([]);
useEffect(() =>
setTasks(_tasks);
, [_tasks]);
function uneek()
const uniqueList = tasks.reduce<ITask[]>((acc, current) =>
const x = acc.find((item: ITask) => item.was === current.was);
return !x ? acc.concat(current) : acc;
, []);
setTasks(uniqueList);
return (
<div className="App">
<h1>Tasks</h1>
tasks.length
? tasks.map(( id, was ) => (
<div key=id>
<h4>was</h4>
</div>
))
: null
<button type="button" onClick=uneek>
uneek
</button>
</div>
);
【讨论】:
以上是关于如何正确使用 TypeScript 和 Array.prototype.reduce?的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript const 断言:如何使用 Array.prototype.includes?
如何在 React 中正确使用 useState 钩子和 typescript?
如何使用 ts-node-dev 和正确的行号在 Visual Studio Code 中调试 Typescript 代码