8000 Fails to infer type parameters from where return value is assigned · Issue #21275 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content
Fails to infer type parameters from where return value is assigned #21275
Closed
@Pajn

Description

@Pajn

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:

  1. The compiler detects that it's not possible to infer Path::T and therefor also Path::A from the arguments
  2. The compiler realizes that the return value is Path<T, T[A]> and is assigned to Path<User, string> and can therefor infer that T = User
  3. As the compiler now knows T it now knows that A is A extends keyof User
  4. It can now infer that A = 'name' from the argument
  5. It now knows that T[A] is User['name'] which is string
  6. Finally, as the return value now is fully resolved as Path<User, string> which is assigned to an argument of type Path<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

Playground Link: https://www.typescriptlang.org/play/#src=type%20Path%3CT%2C%20V%3E%20%3D%20Array%3Cstring%3E%0D%0A%0D%0Afunction%20path%3CT%2C%20A%20extends%20keyof%20T%3E(key%3A%20A)%3A%20Path%3CT%2C%20T%5BA%5D%3E%0D%0Afunction%20path%3CT%3E(path%3A%20string%7CArray%3Cstring%3E)%3A%20Path%3CT%2C%20any%3E%20%7B%0D%0A%20%20if%20(typeof%20path%20%3D%3D%3D%20'string')%20return%20%5Bpath%5D%20as%20Path%3CT%2C%20any%3E%0D%0A%20%20else%20return%20path%20as%20Path%3CT%2C%20any%3E%0D%0A%7D%0D%0A%0D%0Afunction%20field%3CT%2C%20V%3E(%0D%0A%20%20path%3A%20Path%3CT%2C%20V%3E%0D%0A)%20%7B%0D%0A%20%20return%20%7Bpath%7D%0D%0A%7D%0D%0A%0D%0Atype%20User%20%3D%20%7Bid%3A%20string%2C%20name%3A%20string%2C%20birthdate%3F%3A%20Date%7D%0D%0A%0D%0A%2F%2F%20Errors%0D%0Afield%3CUser%2C%20string%3E(path('name'))%0D%0A%0D%0A%2F%2F%20Works%0D%0Afield%3CUser%2C%20string%3E(path%3CUser%2C%20'name'%3E('name'))

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0