Skip to content

--noImplicitAny codefixes infer anonymous object types despite appropriate interfaces in (or out of) scope #28991

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

Open
JoshuaKGoldberg opened this issue Dec 13, 2018 · 3 comments
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript

Comments

@JoshuaKGoldberg
Copy link
Contributor

TypeScript Version: 3.3.0-dev.20181212

Search Terms: noimplicitany infer code fix codefix quick suggested

Code

interface IBox {
    x: number;
    y: number;
}

const shiftBox = (box) => {
    box.x += 1;
    box.y += 1;
}

const box = {
    x: 0,
    y: 0,
};

shiftBox(box);

Expected behavior:

--noImplicitAny suggested fix on the box parameter:

const shiftBox = (box: IBox) =>

Actual behavior:

const shiftBox = (box: { x: any; y: any; }) => {

Related Issues: #13243 (parent tracking quick fixes) and #15114 (discussion on inference difficulties)

If there is an interface available that can satisfy an inferred type in a --noImplicitAny code fix, can we use that? Perhaps with an ordering of possibilities like:

  1. Interfaces already available in the file, by how small they are
  2. User-defined interfaces that could be imported, by how distant the file is
  3. Module types already imported in a user file, by how distant the nearest import is

...where, if multiple interfaces could satisfy the best possibility of those three, we choose the one with the fewest fields?

In code bases that don't explicitly type when unnecessary (e.g. : IBox for variables), I'm finding the --noImplicitAny fixes to be a bit useless for anything other than primitives.

@DanielRosenwasser DanielRosenwasser changed the title --noImplicitAny codefixes infer literal types despite appropriate interfaces in (or out of) scope --noImplicitAny codefixes infer anonymous object types despite appropriate interfaces in (or out of) scope Dec 13, 2018
@DanielRosenwasser DanielRosenwasser added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. In Discussion Not yet reached consensus Effort: Difficult Good luck. labels Dec 13, 2018
@DanielRosenwasser DanielRosenwasser added this to the TypeScript 3.3 milestone Dec 13, 2018
@sandersn
Copy link
Member

Non-primitive inference is indeed a known hole in inferFromUsage.

I haven't published a roadmap for the inferFromUsage codefix, but I prototyped a fix for this last year. At least, I defined the way to choose the "closest type". The part I did not do was create a reliable way to find types that were in scope from a particular definition. The closest-type definition also didn't take scopes into account.

@RyanCavanaugh RyanCavanaugh added Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature and removed In Discussion Not yet reached consensus Effort: Difficult Good luck. Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. labels Mar 7, 2019
@RyanCavanaugh RyanCavanaugh removed this from the TypeScript 3.4.0 milestone Mar 14, 2019
@JoshuaKGoldberg
Copy link
Contributor Author

JoshuaKGoldberg commented Jul 26, 2022

Coming back to this issue, in general I've observed it to be a common annoyance for folks trying to convert React apps to TypeScript. It blocks them from being able to infer types for parameters in common patterns like this one:

import React from 'react';

export const MyComponent = () => {
    // Expected:
    //   event: React.FormEvent<HTMLFormElement>
    // Actual:
    //   event: { preventDefault: () => void }
    const submitHandler = (event) => {
        event.preventDefault();
    };

    return <form onSubmit={submitHandler} />;
};

@sandersn is that code you prototyped 3/4 years ago still available & something you could post here?

@RyanCavanaugh is there any particular feedback this issue is still waiting on? I don't see any reason to block it from coming in.

@sandersn
Copy link
Member

Well, I found this unrelated gem, and I did lots of related prototyping in:

The latter branch is the same as the former but has one more commit, which is very large because I forked most of the services layer for some reason.

That's all I found, though. Those branches are earlier than the experiment I'm thinking of, I'm pretty sure. In theory the only thing that's missing is some way to access the list of types that get created during checking, since the code to determine if a type is "close enough" to an inferred object type already exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting More Feedback This means we'd like to hear from more people who would be helped by this feature Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants