closure-compiler
closure-compiler copied to clipboard
Add type annotation for tuples
This issue was imported from Closure Compiler's previous home at http://closure-compiler.googlecode.com
The original discussion is archived at: http://blickly.github.io/closure-compiler-issues/#209
I would like to see this added to assist in ES6 destructuring.
Previously closure compiler ignored tuple types:
/**
* @param {[number, string]} foo
*/
but in the latest build these are throwing errors. This severely limits jsDoc usage.
We want to tell sm what we support, and not silently ignore type annotations. We were just silently dropping tuples before, and the programmer might have been left with the impression that we were checking them.
If you want to have them in as documentation, you can always write sth like (omit the @):
param {[number, string]} foo
Is it possible to suppress this warning otherwise?
I ask because I'm aware tuples are not being checked, but I have them is some locations where checks are still needed:
/**
* @param {{foo: Bar, baz: [number, string]}} x
*/
I don't think the warning is suppressible. @MatrixFrog can you double-check this?
Also, I don't think you can get checking for the last example you mentioned, b/c when part of the jsdoc is invalid, the compiler discards the whole thing.
So yes, this change had a few drawbacks unfortunately, but overall we think it's a positive change. We'll re-add the tuple syntax when we actually type check it.
Bummer, well it would be nice to be able to set a flag to coerce tuple syntax to a ?
in the mean time. That way existing type documentation can remain accurate without sacrificing all static checks.
@suppress {nonStandardJsDocs}
might work, but I'm not sure.
Any progress on this? So far we've tried to use
/** @type {{0: number, 1: string}} */
but looks like it's not actually working.
No, we haven't worked on tuples yet, and they're not in the immediate horizon, so they won't happen for a few months for sure.
What about starting with {[a, b]}
as an alias for {!Array<a|b>}
? The latter is already the best we can do for many of these types, and then we can work on teaching NTI to deal with them better at some point later. (This could also provide a nice "carrot" for switching to NTI)
I generally want to avoid allowing syntax in such a way that it implies we're doing some checking that we are not actually doing. If we're going to do that I'd like to at least emit a warning when the OTI runs, saying that this isn't actually being checked the way the user probably thinks it is.
Agree with Tyler. There is no rush to add the syntax until we're ready to add semantics as well. When we've added syntax early in the past it has led to issues, eg, all sorts of generic-type syntax was allowed before we supported generics, and was hard to migrate after we added generics.
I'd like to bring this one back on the radar. Specifically, the issue I'm running into is lack of type checking on the ES6 Map
constructor. This is not caught by the compiler:
new Map([['key', 'value', 'notsupposedtobehere'], ...]);
This issue corresponds w/ this TODO in the externs: https://github.com/google/closure-compiler/blob/master/externs/es6_collections.js#L23
Now that ES6 is being openly encouraged, enforcing correct uses of Map
is more important.
This is definitely something we want to support, but it's blocked on NTI. We can't implement this support until NTI lands, but once it does, this is very high priority.
@shicks What is NTI, please? Is there a ticket we can follow?
NTI is the new type inference. Not sure where the progress is being tracked, though there's an issue label where you can see some of the outstanding issues.
Ultimately, though, it's not just about NTI being feature-complete and fully compatible with the entire compiler (which is very close), it's also about ensure projects that currently compile with OTI (old type inference) can migrate to NTI with minimal pain. We're working on a compatibility mode that should hopefully make this smoother.
The upshot is that we're not likely to add any brand new (backwards-incompatible) features to the type system until NTI is on by default.
This is unblocked now, so we should address it soon.
One open question is how to infer array literals. I believe TypeScript treats tuples as read-only, which is nice, but it means that tuples aren't really proper subtypes of !Array
, which is too bad (since the mutation methods are not usable). But it would be nice to infer [1,2]
as [number, number]
if that would silently upcast to !Array<number>
when necessary. Also, how do we infer []
? If we take a read-only stance then it's basically !Array<bottom>
, but the main reason to create an empty array is because you intend to add things to it. Forcing users to explicitly annotate the intended type might not be a bad idea, but it also might not be feasible.
I implemented a class that supports the same methods as the native Map
type. I am unable to document the type yielded by the entries()
generator method ([key, value]
).
Any progress on the tuple/fixed-shape-array support?
Best not to wait for JSDoc. Just permit tuples for now:
/** @type {[number, number, number]} */
let x = [0, 0, 0];
Just treat an empty tuple as a useless variable for now (equivalent to a unit type):
/** @type {[]} */
let x = [];
// x has one value, and can never be destructured.
Are there any updates on this? This feature request is now over 13 years old, and the last update of "this is unblocked now, so we should address it soon" was over 5 years ago.
As many have already pointed out, the lack of tuple types is very annoying since it even prevents the proper annotation of types for JavaScript's built-in APIs, not to mention things like React.useState
.
A lot has happened since that old update from @shicks
Sadly, I don't think there's any chance at all that we will ever add tuple types, unless some very motivated person from outside Google contributes it. There are just far too many priorities ahead of it.
Sorry.