google / google/closure-compiler

Confusing type checking behavior for generic Object & IObject

Open
#1,937 3 comments 0 reactions 1 assignee Claimed by @brad4d View on GitHub
Dominant language
JavaScript
Stars
7.7k
Forks
1.2k
Avg merge
2d 12h
Merged PRs (30d)
6

Description

This document
https://developers.google.com/closure/compiler/docs/js-for-compiler#types

Says to define generic parameters for object like this.
`{Object}`

However, our standard extern definition for Object is not templatized
https://github.com/google/closure-compiler/blob/master/externs/es3.js#L302

On the other hand IObject is
https://github.com/google/closure-compiler/blob/master/externs/es3.js#L127

Consider this code:

```js
/** @type {Object} */
var a = {};
a['foo'] = 5;

/** @type {IObject} */
var b = {};
b['foo'] = 5;
```

https://jscomp-debug.googleplex.com/#input0%3D%252F**%2520%2540type%2520%257BObject%253Cstring%252C%2520string%253E%257D%2520*%252F%250Avar%2520a%2520%253D%2520%257B%257D%253B%250Aa%255B'foo'%255D%2520%253D%25205%253B%250A%250A%252F**%2520%2540type%2520%257BIObject%253Cstring%252C%2520string%253E%257D%2520*%252F%250Avar%2520b%2520%253D%2520%257B%257D%253B%250Ab%255B'foo'%255D%2520%253D%25205%253B%26input1%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3D1%26CHECK_SYMBOLS%3D1%26CHECK_TYPES%3D1%26CLOSURE_PASS%3D1%26LANG_IN_IS_ES6%3D1%26MISSING_PROPERTIES%3D1%26PRESERVE_TYPE_ANNOTATIONS%3D1%26PRETTY_PRINT%3D1%26TRANSPILE%3D1

If NTI is **disabled**, this code gives 3 warnings.

```
input0:3: WARNING - assignment
found : number
required: string
a['foo'] = 5;
^

input0:6: WARNING - initializing variable
found : {}
required: (IObject|null)
var b = {};
^

input0:7: WARNING - assignment
found : number
required: string
b['foo'] = 5;
^
```

This seems wrong to me because:
1. The compiler doesn't complain about the extraneous template parameters on `Object`.
2. The compiler shouldn't complain about the assignment of `{}` to `b`.

With NTI **enabled**, it gives only one.

```
input0:7: WARNING - The right side in the assignment is not a subtype of the left side.
Expected : string
Found : number

b['foo'] = 5;
^
```

This seems wrong to me because:
1. The compiler doesn't complain about the extraneous template parameters on `Object`.
2. It also completely ignores the parameters when typechecking the assignment to `a['foo']`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.