Common types in higher order functions

I would like to use the generic type as a parameter in the inner function of a higher order function. However, when I do this, the parameter on the external function loses its types (becomes any ).

Here is an example of what I'm trying to do. I expect to get an error on line 2.

 type TestFunc = <T>(outerArg: string) => (innerArg: T) => number const test: TestFunc = <T>(outerArg) => (innerArg: T) => innerArg ? outerArg * 3 : 0 // no error because `outerArg` is `any` (unexpected) 

When innerArg not generic, I get the expected error:

 type TestFunc = (outerArg: string) => (innerArg: boolean) => number const test: TestFunc = (outerArg) => (innerArg: boolean) => innerArg ? outerArg * 3 : 0 // error because `outerArg` is `string` (expected) 

Question

In line 2 in the first example, outerArg is of type any . In line 2 in the second example, outerArg is of type string . Why are they different?


More details

My goal is to specify T to define an external function. For instance:

 type TestFunc = <T>(outerArg: string) => (innerArg: T) => number const test: TestFunc = (outerArg) => (innerArg) => innerArg ? outerArg.length * 3 : 0 const test2: TestFunc = <T>(outerArg) => (innerArg: T) => innerArg ? outerArg * 3 : 0 // want error const fourBool = test<boolean>('str') console.log(fourBool(true)) console.log(fourBool(1)) // want error const fourNum = test<number>('str') console.log(fourNum(true)) // want error console.log(fourNum(1)) 

Here he is at the typescript playground .

+5
source share
2 answers

You have two functions:

1) A function with a common type that returns a number,

2) and a function that takes a number and returns a common one.

As you mentioned in the comments, you are using an arrow function with a type parameter, but this will not work for both functions. You can declare your inner function as general, and your outer function with a parameter of type:

 type InnerFunc<T> = (inner: T) => number; type TestFunc = <T>(outer: number) => InnerFunc<T>; const test: TestFunc = <T>(outerArg: number) => (innerArg: T) => innerArg ? outerArg * 3 : 0; const fourBool = test<boolean>(4); fourBool(true); // OK fourBool(1); // error 
+2
source

It looks like this could be a compiler or design error.

But now it can work like a job where you attach a generic type to a function using a generic type.

 type TestFunc = (outerArg: string) => <T>(innerArg: T) => number 

OK, so you would like to approach him to do what you want:

 type TestFunc = (arg1: string) => <T>(a: T) => number type Number1 = (a: number) => number const test: TestFunc = (arg1) => (a) => a ? (arg1 ? 1 : 2) : 0 const num1: Number1 = test("blah") // OR const newNum1 = <Number1>test("bleh") 

There will be an error message above if you put arg1 as you did before, and it will give you the general form you wanted before. You will notice that if you incorrectly define the "subtype", it will also give a compilation error.

For completeness, there is a simpler solution here (pretty much what cdbajorin did in his solution):

 type TestFunc1 = <T>(arg1: string) => (a: T) => number const test1: TestFunc1 = (arg1: string) => a => a ? (arg1 ? 1 : 2) : 0 const newNum2 = test1<number>("bluh") 
+1
source

Source: https://habr.com/ru/post/1270439/


All Articles