如何正确使用 Array.prototype.reduce 的 TypeScript?
How to use TypeScript with Array.prototype.reduce correct?
我有以下 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'.
使用更多类型的指标。看到这个 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;
}, []);
仅供参考,这里是一个使用 useState
.
在 React 组件中使用的示例
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>
);
}
我有以下 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'.
使用更多类型的指标。看到这个 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;
}, []);
仅供参考,这里是一个使用 useState
.
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>
);
}