google / google/closure-compiler

Cannot use properties as types

Open
#2,732 8 comments 0 reactions 0 assignees View on GitHub
OTI
Dominant language
JavaScript
Stars
7.7k
Forks
1.2k
Avg merge
2d 12h
Merged PRs (30d)
6

Description

```
class Parent {}
const Obj = {};
Obj.Alias = Parent;
class Child extends Obj.Alias {} // Bad type annotation. Unknown type Obj.Alias
```
[Link](https://closure-compiler-debugger.appspot.com/#input0%3Dclass%2520Parent%2520%257B%257D%250Aconst%2520Obj%2520%253D%2520%257B%257D%253B%250AObj.Alias%2520%253D%2520Parent%253B%250Aclass%2520Child%2520extends%2520Obj.Alias%2520%257B%257D%26input1%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CHECK_TYPES%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue)

The error here stems from the `@extends {Obj.Alias}` in the transpiled code.

This causes a bug in ES6 module rewriting. If a class is exported directly then things are fine:

```
export class Parent {
static staticFunction() { return 'Parent.staticFunction'; }
}
```
```
import { Parent } from './input0';
class Child extends Parent {}
```
[Link](https://closure-compiler-debugger.appspot.com/#input0%3Dexport%2520class%2520Parent%2520%257B%250A%2520%2520static%2520staticFunction()%2520%257B%2520return%2520'Parent.staticFunction'%253B%2520%257D%250A%257D%26input1%3Dimport%2520%257B%2520Parent%2520%257D%2520from%2520'.%252Finput0'%253B%250A%250Aclass%2520Child%2520extends%2520Parent%2520%257B%257D%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CHECK_TYPES%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue)

Note the type annotation of the extends ends up being Parent$$module$input0.

But if we export using export specs there's an error.

```
class Parent {
static staticFunction() { return 'Parent.staticFunction'; }
}
export { Parent };
```
```
import { Parent } from './input0';
class Child extends Parent {} // Bad type annotation. Unknown type module$input0.Parent
```
[Link](https://closure-compiler-debugger.appspot.com/#input0%3Dclass%2520Parent%2520%257B%250A%2520%2520static%2520staticFunction()%2520%257B%2520return%2520'Parent.staticFunction'%253B%2520%257D%250A%257D%250A%250Aexport%2520%257B%2520Parent%2520%257D%253B%26input1%3Dimport%2520%257B%2520Parent%2520%257D%2520from%2520'.%252Finput0'%253B%250A%250Aclass%2520Child%2520extends%2520Parent%2520%257B%257D%26conformanceConfig%26externs%26refasterjs-template%26includeDefaultExterns%3Dtrue%26CHECK_SYMBOLS%3Dtrue%26MISSING_PROPERTIES%3Dtrue%26TRANSPILE%3Dtrue%26CHECK_TYPES%3Dtrue%26CLOSURE_PASS%3Dtrue%26PRESERVE_TYPE_ANNOTATIONS%3Dtrue%26PRETTY_PRINT%3Dtrue)

Note the type annotation is now module$input0.Parent.

Appears to be an OTI only bug, but seems pretty important.

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.