TypeScript 如何在数组的 Reduce 函数中设置累积值和初始值的类型

TypeScript how to set types for accumulated Value and initialValue on Reduce function on an array

我在 typescriptlang.org(typescript playground)

上有当前代码 运行

我已经阅读了类型在 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[]) = > 汽车'。 参数类型 'acc' 和 'previousValue' 不兼容。 类型 'Car' 不可分配给类型 'number'.

Overload 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'.


问题

我可能遗漏了一个简单的步骤,但编译器抱怨我输入为数字的累加器和我输入为汽车的汽车似乎给我上面记录的错误。

我只是想知道为什么我不能将类型设置为我的累加器作为数字。以后我应该如何在 reduce 函数中设置类型?

您收到错误的原因是您的 reduce 回调没有正确实现。它应该是 return 遍历数组的每个元素后的 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 函数中 return 一个数字(然后记录它)。提醒自己和编译器的一个好方法是添加一个显式 return 类型,如下所示:

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 函数中使用类型声明。原因是 car 的类型是从 cars 的类型推断出来的,而 acc 的类型是从 reduce 函数的第二个参数推断出来的:0.

最后一点,我想补充一点,以上所有内容都假设您只是在玩弄这门语言。如果您真的打算计算在您的汽车阵列中注册的汽车数量,一个可能更简单的方法是

cars.filter(car => car.registered).length