Skip to content

Design Meeting Notes, 6/1/2018 #24593

Closed
Closed

Description

--strictAny

#24423

  • Talked about this last time, but no implementation.

  • Now we have an implementation and data.

  • Came from conversation with the Hack team.

    • (which, funny, was inspired)
  • Background: problem today is that any is assignable in both directions.

    • Problem is often that a user wrote any in a declaration file because they were lazy or just scaffolding things.
      • But that means that any consumer of the .d.ts file has no way to defensively avoid assigning any to anything else.
    • This PR removes the "bottom-ness" from any - makes any a top type.
  • Tried running --strictAny on DefinitelyTyped

    • Not on tests - tests have too much breakage.

    • Some things got broken - declaration files were

    • Much of the time it's just declaration authors being a little lazy.

      • Instantiating generics with any
        • But hey, even we're lazy! We instantiate the prototype property on generic classes with any across.
      • Using any in derived classes.
    • Why is any not assignable to Record<string, any>>

      • Ehh, maybe it should be.
    • There are some issues with signatures like (x: any, y: any, ...zs: any[]) => any.

      • Now any is subject to contravariant checking.
      • Again, can tell users to use never instead of any.
    • Issues with SVGElement not being assignable to Element.

      • DOM in general isn't sound, so... :(
    • Then there's the "covariant event emitter pattern".

      once(event: string, listener: (...args: any[]) => void): this;
      once(event: "close", listener: () => void): this;
      once(event: "drain", listener: () => void): this;
      once(event: "error", listener: (err: Error) => void): this;
      once(event: "finish", listener: () => void): this;
      once(event: "pipe", listener: (src: Readable) => void): this;
      once(event: "unpipe", listener: (src: Readable) => void): this;
  • never?

    • never isn't very intuitive
    • We've tried to help users reason about it as a value that can never occur.
  • The hard-to-solve problems really come from any in contravariant positions.

  • Tried running this on the compiler.

    • Finds some questionable things.
    • commandLineParser is sloppy.
    • Calls to Array() always return an any[].
      • Probably should move the generic overload to the top?
        • Does that work right?
    • isArray is a predicate on Array<{}>
    • Functions with overloads in derived classes with an any in the middle.
      • No.
    • Did this catch any legitimate bugs?
      • commandLineParser had a lot of questionable behavior.
    • Also, like prototypes of generic classes, there are some places where any never occurred but the type checker - for example, erased signatures.
  • Really don't like as never

    • None of us does.
  • Really two usages of any that have been conflated:

    1. I was lazy.
    2. "Ehh, shut up you stupid type-checker."
  • The answer may just be to tell people to go through their files and return unknown.

  • Have a list of places any just appears:

    • Type parameters of prototype property in generic class
    • String index signature in implied type of binding pattern (function f({...x}))
    • Implied type of omitted element in array binding pattern (function f([,,x]))
    • Catch clause variables
    • Shorthand ambient modules
    • Union signature with only some explicit 'this' types
    • Types of properties in object from inference to 'keyof T'
    • Type of 'super' in object literal expressions
    • 'yield' expressions
  • Not sure about this feature.

    • Part of the reason we went in this direction is because any has become so conflated and prevalent.
      • Library authors don't always know how users intend to use these things.
  • Some users really want a more capable unknown.

  • Some users really want a dynamic instead of an any.

  • What about per-file strict-ness?

    • May cause a lot of user confusion.
  • If we did this all over, we could have considered unknown to be treated as "effectively any" for usage, still not assignable.

  • Can't imagine we would use this in --strict

  • Would we use this feature?

    • Yes.
      • But we're also the freaking TypeScript team.
  • We'd like to get feedback from users based on the current behavior and see if it's truly paletable.

"Loose mode" in .ts files vs. TypeScript in .js files

#22665
#23906

  • Hard to reason about the semantics
  • Webpack migration to checkJs has been instructive
    • But we're not trying to solve that in these proposals.
  • Two things in checkJs that make things different.
    • JSDoc comments
    • Change how we check things.
  • So maybe instead of a "loose mode", it's more like allowJsDoc.
    • Also errors when your JSDoc and TypeScript annotations disagree! :D
  • So is tooling not enough here?
  • Now we actually have rename file support - maybe when you rename a .js file to a .ts file, we should offer to migrate the file.
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

    Design NotesNotes from our design meetings

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions