Skip to content

TS doesn't properly infer generic callback <T>(x: X<T>) => T when providing (x) => new T() (parameter defined without type)Β #63377

@denis-migdal

Description

@denis-migdal

πŸ”Ž Search Terms

Not sure of the relevant keywords.
Didn't found related issues.

πŸ•— Version & Regression Information

Tested in 6.0.2

⏯ Playground Link

Playground Link

πŸ’» Code

// see Playground for full types definitions.
type ControllerProvider<T> = ( hooks : HookProvider<T> ) => T; // also tested with NoInfer<>

export default function createViewClass2<T>( _test: ControllerProvider<T> ) {}
//

createViewClass2( // any: nok
    (hooks) => { return new A(hooks) }
)
createViewClass2( // A: ok
    () => { return new A(null as any) }
)
createViewClass2( // A: ok
    (hooks: any) => { return new A(hooks) }
)
createViewClass2( // A: ok
    (hooks: HookProvider<A>) => { return new A(hooks) }
)
createViewClass2( // A: ok
    (hooks): A => { return new A(hooks) }
)

πŸ™ Actual behavior

The generic type is inferred as any when we define the parameter without an explicit type, i.e. (a) => ....

πŸ™‚ Expected behavior

This should properly infer the type, just as when we:

  • do not define the parameter, i.e. () => ...
  • define the parameter as any, i.e. (a: any) => ...

Additional information about the issue

The fact that in the cases () => ... and (a: any) => ..., TS is able to properly infer the generic type, seems to show that this isn't a TS limitation, but more of an oversight or a bug ?

EDIT: my guess is that TS tries first to infer the type of the parameters before inferring the return type. For that it tries to infers the callback type, and infer the generic type as any. Only then it infers the return type, but the callback type already has been inferred, so the generic type stays any. ?

I guess that using it properly requires 2 passes that TS wants to avoid, for performances reasons ?

  1. Infer the callback type, then the parameter type (T = any).
  2. Infer the return type.
  3. If the return type does not depends on the parameter type, try to re-infer the callback type ?
  4. If the callback type is more precise, quick check for stability (?)

This is pure speculations on my part.

Note: Using NoInfer<> on the parameter type doesn't seem to solve this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions