Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending empty tuple in generic functions causes compiler to infer arrays as tuples #31434

Closed
ipotuzhnov opened this issue May 16, 2019 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@ipotuzhnov
Copy link

TypeScript Version: 3.4.5

Search Terms:
empty tuple, type inference, generic function

Code
Basically I'm writing a generic function with dynamic type mapping. I think this use case is pretty common for database drivers and JSON validators and I found some related issues. There is a workaround and I want to confirm whether it is intended behavior or a bug.

interface TypeMap { STRING: string; NUMBER: number;}
type MapTypes<T> = {
  [P in keyof T]: T[P] extends keyof TypeMap ? TypeMap[T[P]] : never
};

declare function fromArray<T extends ReadonlyArray<keyof TypeMap>>(
  types: T, params: MapTypes<T>): void;

fromArray(['STRING', 'NUMBER', 'STRING'], ['abc', 123, 'xyz']);  // ok
// the default behavior is to infer types in array as type union
fromArray(['STRING', 'NUMBER', 'STRING'], ['abc', '123', 'xyz']);  // no error
fromArray(['STRING', 'NUMBER', 'STRING'] as const, ['abc', '123', 'xyz']);  // error

declare function fromTuple<T extends([] | ReadonlyArray<keyof TypeMap>)>(
  types: T, params: MapTypes<T>): void;

fromTuple(['STRING', 'NUMBER', 'STRING'], ['abc', 123, 'xyz']);  // ok
// T extends([]|MyType) cases the compiler to infer array as tuple
fromTuple(['STRING', 'NUMBER', 'STRING'], ['abc', '123', 'xyz']);  // error
fromTuple(['STRING', 'NUMBER', 'STRING'] as const, ['abc', '123', 'xyz']);  // error

Expected behavior:
Type of the array literal is inferred as array of union type.

Actual behavior:
Type of the array literal is inferred as tuple when T extends []|MyType is used in generic function.
I'd prefer it to be the expected behavior, but I didn't find any tests for that use case.

Playground Link:
You can see the same behavior in the playground

Related Issues:
#13151
#22679

Related PR
This PR includes a similar test, but it there is no test for empty tuple and array combination #26676

@ahejlsberg
Copy link
Member

This is working as intended. We only infer tuple types when the contextual type is or contains a tuple-like type.

@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label May 16, 2019
@ipotuzhnov
Copy link
Author

@ahejlsberg Great, thank you for confirming.

Can I add some tests for this behavior then? I wasn't able to find anything similar by grepping tests directory (grep 'extends \[\]' -r tests/).
There are tests that check a combination of two tuples, but not a combination of a tuple and array.

@ahejlsberg
Copy link
Member

Yes, it is the intended behavior. See #27179 (comment) for the recommended pattern.

@ipotuzhnov
Copy link
Author

Thank you for the link. I think I've seen that issue, but didn't go through all comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

2 participants