0

I don't know why I have an error message

teste.ts:41:18 - error TS2345: Argument of type 'T' is not assignable to parameter of type 'number'.

in the following code

function carre1<T>(x: T):T {
    x = Math.pow(x, 2);
    return x;
}
console.log(carre1<number>(0));
console.log(carre1<number>(2));
console.log(carre1<number>(5));
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    Because Math.pow can *only* take numbers. You could try ``, but basically this is a bad candidate for a generic function. – jonrsharpe Feb 22 '20 at 08:31
  • Thank you jonrsharpe for your message , but same errore. –  Feb 22 '20 at 10:50
  • function carre1(x: T) { x = Math.pow(x, 2); return x; } console.log(carre1(0)); // 0 console.log(carre1(2)); // 4 console.log(carre1(5)); // 25 –  Feb 22 '20 at 10:51
  • No, you get a *different* error. The point that a function where you know what types are needed isn't a useful demonstration of generics stands. – jonrsharpe Feb 22 '20 at 10:58

2 Answers2

0

TypeScript knows it is a number:

function carre1<T>(x: T):T {
  // x must be a number because Math.pow only takes a number
    x = Math.pow(x, 2);  
    return x;
}

Generics are most useful for specialising functions that take an object as a parameter.

interface HasXProp {
  x: number
}

function carre1<T extends HasXProp>(something: T): T {
    const x = Math.pow(something.x, 2);  
    return { ...something, x };
}
Josh Wulf
  • 4,727
  • 2
  • 20
  • 34
  • 1
    Hello Josh , thank you for your help ,but i meet little error in the code ,` "teste.ts:60:49 - error TS1005: '?' expected. 60 function carre1(something: T extends HasXProp): T {" ` I put optional parameters "?" but without success. –  Feb 23 '20 at 11:33
  • I fixed that. Putting the `extends` statement in the parameter typing, versus the Generic parameter, makes it part of a ternary. – Josh Wulf Feb 24 '20 at 03:16
0

I believe that you are trying to explore generics and its usages. Perhaps the function that you have just shared is not really a good case study for generics. The first parameter of Math.pow is expected to be a number type, which is why you are getting the error. Imagine if you are invoking the function as such:

console.log(carre1<string>("abc"));

It will cause runtime error, which is why it was prevented by TS transpilation process in the first place.

If we look at the function from a functionality perspective, there is no need for it to be generic at all. It is understood to be a number already. The function could then be written as something like following, without generics:

function carre1(x: number): number {
    x = Math.pow(x, 2);
    .... some other logics?
    return result;
}

However, if we insist on using generic parameter, perhaps the following can be considered. Though the generics are not being useful in this case:

function carre1<T>(x: T ): T {
    let y:any = Math.pow(x as any, 2);
    return y;
}

Consider this following function. It could be a useful example of Generics as the function should be able to accept parameter of any type. In another word, the function logic is type independent.

function deepCopy<T>(data: T): T {
    return JSON.parse(JSON.stringify(data));
}

Another good use case of generics could be implementing a Data or Object Mapper. Refer to this example shared here https://stackoverflow.com/a/52759912/6096478

DriLLFreAK100
  • 1,575
  • 2
  • 16
  • 26