closure-compiler icon indicating copy to clipboard operation
closure-compiler copied to clipboard

Add type annotation for tuples

Open blickly opened this issue 10 years ago • 22 comments

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

blickly avatar Apr 29 '14 20:04 blickly

I would like to see this added to assist in ES6 destructuring.

concavelenz avatar May 02 '14 18:05 concavelenz

Previously closure compiler ignored tuple types:

/**
* @param {[number, string]} foo
*/

but in the latest build these are throwing errors. This severely limits jsDoc usage.

eborden avatar Dec 02 '14 21:12 eborden

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

dimvar avatar Dec 02 '14 21:12 dimvar

Is it possible to suppress this warning otherwise?

eborden avatar Dec 02 '14 21:12 eborden

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
*/

eborden avatar Dec 02 '14 21:12 eborden

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.

dimvar avatar Dec 02 '14 21:12 dimvar

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.

eborden avatar Dec 02 '14 21:12 eborden

@suppress {nonStandardJsDocs} might work, but I'm not sure.

MatrixFrog avatar Dec 02 '14 23:12 MatrixFrog

Any progress on this? So far we've tried to use

/** @type {{0: number, 1: string}} */

but looks like it's not actually working.

aslushnikov avatar Oct 02 '15 16:10 aslushnikov

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.

dimvar avatar Oct 02 '15 16:10 dimvar

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)

shicks avatar Jun 06 '16 21:06 shicks

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.

MatrixFrog avatar Jun 06 '16 21:06 MatrixFrog

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.

dimvar avatar Jun 06 '16 21:06 dimvar

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.

joeltine avatar Jun 01 '17 04:06 joeltine

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 avatar Jun 05 '17 21:06 shicks

@shicks What is NTI, please? Is there a ticket we can follow?

lll000111 avatar Jul 29 '17 08:07 lll000111

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.

shicks avatar Aug 01 '17 00:08 shicks

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.

shicks avatar Feb 28 '18 01:02 shicks

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?

stumash avatar Dec 26 '19 15:12 stumash

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.

alexchandel avatar May 22 '20 20:05 alexchandel

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.

data-enabler avatar Aug 29 '23 18:08 data-enabler

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.

brad4d avatar Aug 29 '23 19:08 brad4d