javascript - TypeScript如何在数组上的Reduce函数上设置累积值和初始值的类型
问题描述
我在 typescriptlang.org(打字稿游乐场)上运行当前代码
我已经阅读了 typeScript 中类型的重要性以及如何在函数中使用它们。但是,我正在努力在此 reduce 方法中添加以下类型:
// Types for car
type Car = {
name:string,
age:number,
registered: boolean
};
// Reduce function to hopefully get the total number of cars that are registered.
function totalRegisteredCars(cars:Car[]) {
cars.reduce((acc:number , car:Car) => {
if(car.registered === true ) {
acc + 1;
}
},0);
}
var cars = [
{name:'vw' , age: 30, registered: true},
{name:'vw' , age: 32, registered: true},
{name:'Merc' , age: 25, registered: false},
{name:'bmw' , age: 20, registered: false},
{name:'bmw' , age: 21, registered: true},
{name: 'ford', age: 31, registered: false},
{name: 'pinto', age: 43, registered: false},
{name: 'uno', age: 41, registered: true},
{name: 'ford', age: 30, registered: true},
{name: 'Mustang', age: 19, registered: false}
];
console.log(totalRegisteredCars(cars));
在https://www.typescriptlang.org/play中有此内容时,我收到以下错误:
错误信息
没有重载匹配此调用。重载 1 of 3, '(callbackfn: (previousValue: Car, currentValue: Car, currentIndex: number, array: Car[]) => Car, initialValue: Car): Car',给出以下错误。
'(acc: number, car: Car) => void' 类型的参数不可分配给 '(previousValue: Car, currentValue: Car, currentIndex: number, array: Car[]) => Car' 类型的参数。参数“acc”和“previousValue”的类型不兼容。“汽车”类型不能分配给“数字”类型。
重载 2 of 3, '(callbackfn: (previousValue: number, currentValue: Car, currentIndex: number, array: Car[]) => number, initialValue: number): number',给出以下错误。'(acc: number, car: Car) => void' 类型的参数不可分配给 '(previousValue: number, currentValue: Car, currentIndex: number, array: Car[]) => number' 类型的参数。类型 'void' 不能分配给类型 'number'。
问题
我可能错过了一个简单的步骤,但编译器抱怨我输入为数字的累加器和输入为 Car 的汽车似乎给了我上面记录的错误。
我只想知道为什么我不能将累加器的类型设置为数字。将来我应该如何在reduce函数中设置类型?
解决方案
您收到错误的原因是您的 reduce 回调未正确实现。它应该在遍历数组的每个元素后返回 reduce 操作的结果。
function totalRegisteredCars(cars: Car[]) {
cars.reduce((acc:number , car:Car) => {
let newReducedValue = acc;
if(car.registered === true ) {
newReducedValue = acc + 1;
}
return newReducedValue;
}, 0);
}
当然,没有必要写这么多行,但我想把问题出在哪里。这是编写相同内容的另一种方法:
cars.reduce((acc: number, car: Car) => acc + car.registered ? 1 : 0, 0);
// or even use car.registered by itself, JS will cast it to a number,
// I just prefer to make it more obvious
我注意到您的代码的另一件事是类型签名totalRegisteredCars
实际上是(cars: Car[]) => void
,因为函数本身没有 return 语句。我们将 Cars 数组减少为一个数字,但随后我们对该数字什么也不做。
您可能打算从您的totalRegisteredCars
函数中返回一个数字(然后记录它)。提醒自己和编译器的一个好方法是添加一个显式返回类型,如下所示:
function totalRegisteredCars(cars: Car[]): number {
一旦你这样做,你会注意到你得到一个新的错误:
A function whose declared type is neither 'void' nor 'any' must return a value. (2355)
此时我们可以说“谢谢,Typescript”并修复代码以实现我们的意图,同时思考类型有多大帮助。
function totalRegisteredCars(cars: Car[]): number {
return cars.reduce((acc, car) => acc + car.registered ? 1 : 0, 0);
}
请注意,在我的最新示例中,我根本没有在 lambda 函数中使用类型声明。原因是类型 ofcar
是从 type of 推断出来的cars
,而类型 ofacc
是从函数的第二个参数推断出来的reduce
:0
。
最后一点,我想补充一点,以上所有内容都是假设您只是在使用该语言。如果您真的打算计算在您的汽车阵列中注册的汽车数量,一种可能更简单的方法是
cars.filter(car => car.registered).length
推荐阅读
- c++ - 从类继承时,继承的变量是否通过父类被继承的类重新定义?
- eclipse - 为什么 -vm 在 eclipse.ini 中取两个值?
- c++ - 大高度图插值
- javascript - 如何通过 Google Script 获得每个单独列的单独总和?
- c# - 如何在不同的线程上进行同步调用
- python-3.x - 使用函数拆分一个单词,然后对单词进行上下排列
- javascript - 从我的谷歌电子表格设置电子邮件系统。除了在正文中添加图像之外,我还有其他一切工作
- spring-boot - Spring Cloud Gateway 可以与非异步的微服务一起使用吗?
- c# - 更新数据库并使用数据表和数据适配器
- http - 密码重置 (Parse-server/Heroku) -> {"error":"unauthorized"}