Closed
Description
TypeScript Version: 2.7.0-dev.20180117
Search Terms:
generic, return, infer, inference, type parameter
Code
type Path<T, V> = Array<string>
function path<T, A extends keyof T>(key: A): Path<T, T[A]>
function path<T>(path: string|Array<string>): Path<T, any> {
if (typeof path === 'string') return [path] as Path<T, any>
else return path as Path<T, any>
}
function field<T, V>(path: Path<T, V>) {
return {path}
}
type User = {name: string}
// Errors
field<User, string>(path('name'))
// Works
field<User, string>(path<User, 'name'>('name'))
Expected behavior:
path should have all type information it needs by the fully typed field call and therefor build without explicit type arguments.
If I can freely imagine the steps the compiler would take:
- The compiler detects that it's not possible to infer
Path::T
and therefor alsoPath::A
from the arguments - The compiler realizes that the return value is
Path<T, T[A]>
and is assigned toPath<User, string>
and can therefor infer thatT = User
- As the compiler now knows T it now knows that A is
A extends keyof User
- It can now infer that
A = 'name'
from the argument - It now knows that
T[A]
isUser['name']
which isstring
- Finally, as the return value now is fully resolved as
Path<User, string>
which is assigned to an argument of typePath<User, string>
there should be no build errors
Actual behavior:
Error: Argument of type '"name"' is not assignable to parameter of type 'never'.
.
Presumably Path::T
is inferred to be {}
and Path::A
naturally then becomes never
Related Issues:
There are many issues related to inference or generics but I can't find any related that I imagines involves the same resolution logic.