Skip to content
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

JSDoc missing syntax for new Map<string, string>() #38876

Open
Raynos opened this issue Jun 1, 2020 · 3 comments
Open

JSDoc missing syntax for new Map<string, string>() #38876

Raynos opened this issue Jun 1, 2020 · 3 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@Raynos
Copy link

Raynos commented Jun 1, 2020

TypeScript Version: 3.7.x-dev.201xxxxx

Search Terms: JSDoc Map generics assignment any unsafe

Code

class MyServer {
  constructor () {
    // new Map is Map<any, any>; cannot call Map constructor with new Map<string, string[]>
    /** @type {Map<string, string[]>} */
    this.functions = new Map()
  }
}

const myServer = new MyServer()
myServer.functions.get('foo')

Expected behavior:

Expected to be able to say what the Map contains when creating a new map. In typescript you can do new Map<string, string[]>() but theres no explicit generic parameter function invocation syntax for JSDoc

Actual behavior:

The type Map<any, any> exists. This fails the eslint rule of no-unsafe-assignment and this fails the no-any rule of tslint etc.

Note that doing something similar for arrays works because there's a special case inference for [] and it also works for Set because the constructor is defined differently and it has generic inference in the initialization statement.

Playground Link: https://www.typescriptlang.org/play?useJavaScript=true#code/MYGwhgzhAECyCeBlApgJwG5ugbwFDWmAHsA7CAF1QFdhyjVoAKASh3wOgHoAqb6AAXLwADshywwwgDwVUASxIBzADTRZCxQG0AugD4AvtG6d2BcgAs5EAHQAzKiVpzSMALzQSyAO5xJLdvq4gbjEZOTQALZIaJgM7p4+CCgYaP5RybF2Dk4u1orI5IwA5LZEREXMuCHgUHDRKQx4BKGyNHQMLGwcXLwCQqI4AIKoqGDwMpQaBkYm3RZWWY7kzmTQ7joBQVUt4ekxWPHedRmplXsNizlkeQXFpeXMQA

Related Issues: Yes, in eslint typescript-eslint/typescript-eslint#2109

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Jun 3, 2020

I think the thing you're encountering has more to do with the fact that we don't look at the contextual types during inference for any invocation expression except for ordinary calls. For example, this works:

class MyServer {
  constructor () {
    /** @type {Map<string, string[]>} */
    this.functions = foo()
  }
}

/**
 * @template T
 * @return {Map<T, T[]>}
 */
function foo() {
  throw ""
}

@DanielRosenwasser DanielRosenwasser added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Jun 3, 2020
@DanielRosenwasser
Copy link
Member

Though it really depends on the problem we're trying to solve. In this case, I think this would be fixed by broadening our inference process, but it's definitely the case that you can't explicitly pass type arguments in JS files.

@Raynos
Copy link
Author

Raynos commented Jun 3, 2020

I think this would be fixed by broadening our inference process

I think that would be a good solution for new Map() and also new Array() ( Although for new Array() you can use [] and the inference does work ).

I understand that inference is not perfect in TypeScript and that being explicit is always an option when inference does not work.

you can't explicitly pass type arguments in JS files.

Unfortunately the explicit syntax does not exist for JS files when it comes to type arguments.

I can't think of anything other then

class MyServer {
  constructor () {
    /** @type {Map<string, string[]>} */
    this.functions = new Map/** @generic {<string, string[]>} */()
  }
}

This a little strange, but I would prefer strange and possible over impossible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
Development

No branches or pull requests

2 participants