1
votes

I have a piece of code:

function reverse<T extends Number, D extends Number>(items: T[], m: D): T[] {
    var toreturn = [];
    for (var i = items.length - 1; i >= 0; i--) {
        (()=>{
            toreturn.push(items[i] * m);
        })();
    }
    return toreturn;
}

var sample = [1, 2, 3];
var reversed = reverse(sample, 10);
console.log(reversed);

My IDE says that there are 2 error here:

Error:(5, 27) TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

Error:(5, 38) TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

It's basically about the entities cannot be multiplied because they are not numbers or other plausible type. I've added extends to the generic definition.

How can this be fixed?

Relevant typescript playground version is here

3

3 Answers

1
votes

You can use type assertion to tell the compiler that you know these will be numbers.

function reverse<T extends number, D extends number>(items: T[], m: D): T[] {
    var toreturn = [];
    for (var i = items.length - 1; i >= 0; i--) {
        (()=>{
            toreturn.push(<number>items[i] * <number>m);
        })();
    }
    return toreturn;
}

var sample = [1, 2, 3];
var reversed = reverse(sample, 10);
console.log(reversed);
1
votes

you used casting or asert you look here Type assertions:

http://www.typescriptlang.org/docs/handbook/basic-types.html

extracted from the link above (basic-types.html):

Type assertions have two forms. One is the “angle-bracket” syntax:

let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;

And the other is the as-syntax:

let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;

function reverse<T extends number, D extends number>(items: T[], m: D): T[] {
    var toreturn = [];

    for (var i = items.length - 1; i >= 0; i--) {
        (()=>{
            toreturn.push(<number>items[i] * <number>m);
        })();
    }
    return toreturn;
}

var sample = [1, 2, 3];
var reversed = reverse(sample, 10);
console.log(reversed);

here


Update:

This might work if you can not use number on extends:

toreturn.push( (<Number>items[i] as number) * (<Number>m as number) );

function reverse<T extends Number, D extends Number>(items: T[], m: D): T[] {
    var toreturn = [];

    for (var i = items.length - 1; i >= 0; i--) {
        (()=>{
            toreturn.push( (<Number>items[i] as number) * (<Number>m as number) );
        })();
    }
    return toreturn;
}

var sample = [1, 2, 3];
var reversed = reverse(sample, 10);
console.log(reversed);

here

1
votes

Kind of annoying, but since your constraint is for Number with a capital N you have to do a type assertion to Number then number:

(items[i] as Number as number) * (m as Number as number)

If it works for how the function is used, you can change the generic constraint to be number instead of Number so you only have to assert to number. Or maybe you didn't really need generics? In that case remove the generics and replace the types T and D with number.

Note there's really no need for the second generic constraint since m's type can just be the base type without affecting the return type, so you could improve it by doing:

function reverseAndMultiplyBy<T extends number>(items: T[], m: number): T[] {
    const toreturn = [];
    for (let i = items.length - 1; i >= 0; i--) {
        toreturn.push((items[i] as number) * m);
    }
    return toreturn;
}