Skip to content

Suggestion: noInferredAny #39633

Open
Open

Description

Search Terms

noImplicitAny inference any noInferredAny

Suggestion

Symbols typed as any reduce the type safety of a program. That's fair if the programmer intended to use any. However it's relatively easy to end up with symbols typed any through type inference chains that are not obvious:

  • 3rd party libraries might return any
  • complex type expressions might infer to any
  • some .d.ts types default generic arguments to any (e.g. Set)

In all these situations, a programmer might write const foo = something(); and expect foo to have a reasonable inferred type. foo being inferred to any is easy to miss in such code, both while editing and while reviewing code.

Proposal: add a compiler option noInferredAny that flags symbols whose type is any and that do not have an explicit type annotation.

Use Cases

  • better type safety for programs
  • detect weak typings in your dependencies
  • more

Examples

const foo1 = returnsAny();  // error
const foo2: any = returnsAny(); // ok
const foo3: string = returnsAny(); // probably ok, programmer gave an explicit type? could also require an explicit cast.
const foo4 = returnsAny() as string;  // ok

const {foo5}: {foo5: string} = returnsAny(); // ok

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Activity

  1. RyanCavanaugh commented on Jul 17, 2020

    @RyanCavanaugh
    Member

    So consider something like

    // Elsewhere
    declare function fn<T = string>(): T extends "foo" ? { p: boolean } : { m: any };
    
    const k = fn();

    Is this an "inferred" any because k.m has type any? If so, how does TypeScript perform an infinite examination of all potential properties (it can't)? If not, is the feature working? Does the access occur on k.m cause the error instead? Or on property access of k.m?

    Thinking about this in terms of only binding an inference to a top-level binding just misses a lot of cases. If you keep poking at this hornet's nest you end up with the proposed --strictAny, #24737. We can revisit that one again later, or if you have more concrete proposal here for exactly what would count as an error and a demonstration of how that would work beyond basic examples, that'd be interesting too

  2. mprobst commented on Jul 20, 2020

    @mprobst
    ContributorAuthor
  3. stefee commented on Sep 5, 2021

    @stefee

    For anyone finding this now and wondering if there is a solution, you can use typescript-eslint with the following rules:

      "rules": {
        "@typescript-eslint/no-unsafe-argument": "error",
        "@typescript-eslint/no-unsafe-assignment": "error",
        "@typescript-eslint/no-unsafe-call": "error",
        "@typescript-eslint/no-unsafe-member-access": "error",
        "@typescript-eslint/no-unsafe-return": "error"
      }

    Links to the documentation for these rules can be found here: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#supported-rules

    You can also add these rules, plus some others, using the recommended-requiring-type-checking preset:

      "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/recommended-requiring-type-checking",
      ]

    You must also add this to your eslint config to allow the eslint plugin find your ts project configuration which enables it to do type-checking:

      "parserOptions": {
        "project": "./tsconfig.json"
      },

    Here's the full docs for the parser config: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#configuration

  4. osdiab commented on Dec 19, 2024

    @osdiab

    Stef (@stefee) 's solution from a few years ago works, though I would love if this were built into TypeScript instead of needing to use typescript-eslint for it, since it is extremely slow and makes many spurious errors in the editor when files change, like this: microsoft/vscode-eslint#1321

    I don't really care if any is being used in library code, but if in my own code I could have TypeScript throw an error basically identically to what Typescript ESLint does with the above set of rules; then that would be perfect for my use cases—so if that can act as a concrete proposal of what exactly counts as an error, and a demonstration of how it would work beyond specific examples, then I hope that remains interesting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions