Skip to content

Add an option not to use implicit any when I create an empty container (for example [], new Set() or new Map()) #61638

@DonaldDuck313

Description

@DonaldDuck313

πŸ” Search Terms

implicit any containers

βœ… Viability Checklist

⭐ Suggestion

Currently, new Map() has type Map<any, any> and new Set() has type Set<any>. I suggest to add an option so that instead new Map() has type Map<never, never> and new Set() has type Set<never>. This should work because Set<never> is assignable to any other set type, and same for maps.

Note that this needs to be an option, otherwise it could break existing code.

πŸ“ƒ Motivating Example

I ran into this issue with code similar to the following:

declare function returnsNullableMap(): Map<number, number> | null;

const myMap = returnsNullableMap() ?? new Map();
myMap.set("", "");    //This compiles but shouldn't

The last line is obviously a mistake since the map contains numbers, not strings. But since new Map() has type Map<any, any>, so does myMap, and the last line compiles.

πŸ’» Use Cases

  1. What do you want to use this for?

I would like to completely avoid the any type in my code, and the fact that the code above actually does contain any is not immediately obvious. I use existing options such as noImplicitAny and useUnknownInCatchVariables to avoid any sneaking in at other places, but apparently any can still sneak in in this case. By the way, I would have expected noImplicitAny to cover this case as well, but apparently it doesn't.

  1. What workarounds are you using in the meantime?

In the specific code above I can use const myMap = returnsNullableMap() ?? new Map<never, never>(); and it works fine, myMap has the correct type (Map<number, number>). Note that in my actual code my types are much more complicated than just number, so using never saves a lot of typing compared to using the actual type. In this simplified example however new Map<number, number>() would have worked just as well.

  1. What shortcomings exist with current approaches?

The main issue is that if I forget the <never, never> (or a similar workaround), my code will contain the any type without making it immediately obvious, allowing mistakes like in the example above. Another minor annoyance is that new Map<never, never>() is more verbose than just new Map(), but I can live with that, what I'm more concerned about is any types sneaking into my code where I don't want them.

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions