Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

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

80%
+6 −0
Q&A TypeScript is unable to infer the correct type for a mapped tuple

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<...

0 answers  ·  posted 2y ago by Moshi‭  ·  edited 2y ago by Moshi‭

#2: Post edited by user avatar Moshi‭ · 2022-04-22T20:16:39Z (almost 2 years ago)
  • 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 by user avatar Moshi‭ · 2022-04-22T04:19:59Z (almost 2 years ago)
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)`?