Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
I was playing around with mapped tuples and came across an interesting case where TypeScript cannot infer the types used: interface Foo<A, B> { (a: A, b: B): any } function test<...
#3: Post edited
- I was playing around with [mapped tuples](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) and came across an interesting case where TypeScript cannot infer the types used:
- ```typescript
- interface Foo<A, B> {
- (a: A, b: B): any
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) {}
- let add: Foo<string, string> = (a, b) => a + b;
- test(add);
- ```
- ```
- error TS2345: Argument of type 'Foo<string, string>' is not assignable to parameter of type 'Foo<unknown, string>'.
- Type 'unknown' is not assignable to type 'string'.
- 80 test(add);
- ~~~
- ```
- Interestingly, this succeeds if `Foo` is an object interface; ex.
- ```typescript
- interface Foo<A, B> {
- a: A,
- b: B,
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }): A {
- throw "unimplemented";
- }
- let foo: Foo<string, string> = {a: '', b: ''};
- let str = test(foo);
- ```
- Though looking at my IDE, and adding a small [compile time assertion](https://abstract.properties/typescript-compile-assertions) shows that it actually can't correctly infer the type of this either; `A` (and thus `str`) has an inferred type of `unknown`, so the problem still shows up, it just doesn't immediately cause an error in this case.
- ```typescript
- let string_assert: typeof str extends string ? true : never = true;
- ```
- ```
- error TS2322: Type 'boolean' is not assignable to type 'never'.
- 13 let string_assert: typeof str extends string ? true : never = true;
- ```
- Thus, my question is two-fold:
- 1. Why does TypeScript fail to infer the correct type in these cases? (Keep in mind that the concrete types for the passed argument should be known; they are even explicitly written.)
2. How can I fix this other than explicitly calling `test<string, string>(add)`?
- I was playing around with [mapped tuples](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) and came across an interesting case where TypeScript cannot infer the types used:
- ```typescript
- interface Foo<A, B> {
- (a: A, b: B): any
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) {}
- let add: Foo<string, string> = (a, b) => a + b;
- test(add);
- ```
- ```
- error TS2345: Argument of type 'Foo<string, string>' is not assignable to parameter of type 'Foo<unknown, string>'.
- Type 'unknown' is not assignable to type 'string'.
- 80 test(add);
- ~~~
- ```
- Interestingly, this succeeds if `Foo` is an object interface; ex.
- ```typescript
- interface Foo<A, B> {
- a: A,
- b: B,
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }): A {
- throw "unimplemented";
- }
- let foo: Foo<string, string> = {a: '', b: ''};
- let str = test(foo);
- ```
- Though looking at my IDE, and adding a small [compile time assertion](https://abstract.properties/typescript-compile-assertions) shows that it actually can't correctly infer the type of this either; `A` (and thus `str`) has an inferred type of `unknown`, so the problem still shows up, it just doesn't immediately cause an error in this case.
- ```typescript
- let string_assert: typeof str extends string ? true : never = true;
- ```
- ```
- error TS2322: Type 'boolean' is not assignable to type 'never'.
- 13 let string_assert: typeof str extends string ? true : never = true;
- ```
- Thus, my question is two-fold:
- 1. Why does TypeScript fail to infer the correct type in these cases? (Keep in mind that the concrete types for the passed argument should be known; they are even explicitly written.)
- 2. How can I fix this other than explicitly calling `test<string, string[]>(add)`?
#2: Post edited
- I was playing around with [mapped tuples](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) and came across an interesting case where TypeScript cannot infer the types used:
- ```typescript
- interface Foo<A, B> {
- (a: A, b: B): any
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) {}
- let add: Foo<string, string> = (a, b) => a + b;
- test(add);
- ```
- ```
- error TS2345: Argument of type 'Foo<string, string>' is not assignable to parameter of type 'Foo<unknown, string>'.
- Type 'unknown' is not assignable to type 'string'.
- 80 test(add);
- ~~~
- ```
- Interestingly, this succeeds if `Foo` is an object interface; ex.
- ```typescript
- interface Foo<A, B> {
- a: A,
- b: B,
- }
function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) {// Do stuff- }
- let foo: Foo<string, string> = {a: '', b: ''};
test(foo);- ```
- Thus, my question is two-fold:
1. Why does TypeScript fail to infer the correct type in the first case, where we pass in a function interface (Keep in mind that the concrete types for the passed argument should be known; they are even explicitly written.)- 2. How can I fix this other than explicitly calling `test<string, string>(add)`?
- I was playing around with [mapped tuples](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) and came across an interesting case where TypeScript cannot infer the types used:
- ```typescript
- interface Foo<A, B> {
- (a: A, b: B): any
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) {}
- let add: Foo<string, string> = (a, b) => a + b;
- test(add);
- ```
- ```
- error TS2345: Argument of type 'Foo<string, string>' is not assignable to parameter of type 'Foo<unknown, string>'.
- Type 'unknown' is not assignable to type 'string'.
- 80 test(add);
- ~~~
- ```
- Interestingly, this succeeds if `Foo` is an object interface; ex.
- ```typescript
- interface Foo<A, B> {
- a: A,
- b: B,
- }
- function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }): A {
- throw "unimplemented";
- }
- let foo: Foo<string, string> = {a: '', b: ''};
- let str = test(foo);
- ```
- Though looking at my IDE, and adding a small [compile time assertion](https://abstract.properties/typescript-compile-assertions) shows that it actually can't correctly infer the type of this either; `A` (and thus `str`) has an inferred type of `unknown`, so the problem still shows up, it just doesn't immediately cause an error in this case.
- ```typescript
- let string_assert: typeof str extends string ? true : never = true;
- ```
- ```
- error TS2322: Type 'boolean' is not assignable to type 'never'.
- 13 let string_assert: typeof str extends string ? true : never = true;
- ```
- Thus, my question is two-fold:
- 1. Why does TypeScript fail to infer the correct type in these cases? (Keep in mind that the concrete types for the passed argument should be known; they are even explicitly written.)
- 2. How can I fix this other than explicitly calling `test<string, string>(add)`?
#1: Initial revision
TypeScript is unable to infer the correct type for a mapped tuple
I was playing around with [mapped tuples](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) and came across an interesting case where TypeScript cannot infer the types used: ```typescript interface Foo<A, B> { (a: A, b: B): any } function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) {} let add: Foo<string, string> = (a, b) => a + b; test(add); ``` ``` error TS2345: Argument of type 'Foo<string, string>' is not assignable to parameter of type 'Foo<unknown, string>'. Type 'unknown' is not assignable to type 'string'. 80 test(add); ~~~ ``` Interestingly, this succeeds if `Foo` is an object interface; ex. ```typescript interface Foo<A, B> { a: A, b: B, } function test<A, Bs extends readonly any[]>(...args: { [K in keyof Bs]: Foo<A, Bs[K]> }) { // Do stuff } let foo: Foo<string, string> = {a: '', b: ''}; test(foo); ``` Thus, my question is two-fold: 1. Why does TypeScript fail to infer the correct type in the first case, where we pass in a function interface (Keep in mind that the concrete types for the passed argument should be known; they are even explicitly written.) 2. How can I fix this other than explicitly calling `test<string, string>(add)`?