I want to type properly for Object method and have the good inference of the functions.
const P = <T,>(x: T) => ({ "foo": (R: Function) => R(x) });
const f = (a: number) => a 1;
const g = (a: number) => a.toString();
const p1 = f(5); //const p1: number // good
const p2 = g(5); //const p2: string // good
const q1 = P(5)['foo'](f); //const q1: any // bad
const q2 = P(5)['foo'](g); //const q2: any // bad
console.log(q1);
console.log(q2);
Any ideas? Thanks!
"use strict";
const P = (x) => ({ "foo": (R) => R(x) });
const f = (a) => a 1;
const g = (a) => a.toString();
const p1 = f(5); //const p1: number // good
const p2 = g(5); //const p2: string // good
const q1 = P(5)['foo'](f); //const q1: any // bad
const q2 = P(5)['foo'](g); //const q2: any // bad
console.log(q1);
console.log(q2);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Using the Function
type is probably a bad idea; it represents an untyped function which accepts any parameters whatsoever and returns the unsafe any
type. That means P
is inferred to have the following type:
const P = <T,>(x: T) => ({ "foo": (R: Function) => R(x) });
/* const P: <T>(x: T) => {
foo: (R: Function) => any;
} */
And so P(x).foo(y)
will always return a value of type any
for all x
and y
. Oops.
If you want the compiler to keep track of both the type of x
and the return type of R
you will need to make the returned function generic and give R
an appropriate function type, like this:
const P = <T,>(x: T) => ({ "foo": <U,>(R: (x: T) => U) => R(x) });
Now it should work as desired:
const q1 = P(5)['foo'](f);
//const q1: number
console.log(q1.toFixed(2)) // "6.00"
const q2 = P(5)['foo'](g);
//const q2: string
console.log(q2.repeat(2)) // "55"