From b3d3b781ab9effea0bcbd0ba8689e4f8aee85669 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Mon, 13 Nov 2017 15:39:08 -0800 Subject: [PATCH] Treat `{}` in `T = {}` as `any` in JS files (#19977) --- src/compiler/checker.ts | 5 +- .../defaultPropsEmptyCurlyBecomesAnyForJs.js | 76 +++++++++++++++++ ...aultPropsEmptyCurlyBecomesAnyForJs.symbols | 70 ++++++++++++++++ ...efaultPropsEmptyCurlyBecomesAnyForJs.types | 81 +++++++++++++++++++ .../defaultPropsEmptyCurlyBecomesAnyForJs.ts | 26 ++++++ 5 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.js create mode 100644 tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.symbols create mode 100644 tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.types create mode 100644 tests/cases/compiler/defaultPropsEmptyCurlyBecomesAnyForJs.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 85033816766..f983abc9cfe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6454,7 +6454,10 @@ namespace ts { } for (let i = numTypeArguments; i < numTypeParameters; i++) { const mapper = createTypeMapper(typeParameters, typeArguments); - const defaultType = getDefaultFromTypeParameter(typeParameters[i]); + let defaultType = getDefaultFromTypeParameter(typeParameters[i]); + if (defaultType && isTypeIdenticalTo(defaultType, emptyObjectType) && isJavaScriptImplicitAny) { + defaultType = anyType; + } typeArguments[i] = defaultType ? instantiateType(defaultType, mapper) : getDefaultTypeArgumentType(isJavaScriptImplicitAny); } } diff --git a/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.js b/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.js new file mode 100644 index 00000000000..63e45ff68b0 --- /dev/null +++ b/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.js @@ -0,0 +1,76 @@ +//// [tests/cases/compiler/defaultPropsEmptyCurlyBecomesAnyForJs.ts] //// + +//// [library.d.ts] +export class Foo { + props: T; + state: U; + constructor(props: T, state: U); +} + +//// [component.js] +import { Foo } from "./library"; +export class MyFoo extends Foo { + member; +} + +//// [typed_component.ts] +import { MyFoo } from "./component"; +export class TypedFoo extends MyFoo { + constructor() { + super({x: "string", y: 42}, { value: undefined }); + this.props.x; + this.props.y; + this.state.value; + this.member; + } +} + +//// [component.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var library_1 = require("./library"); +var MyFoo = /** @class */ (function (_super) { + __extends(MyFoo, _super); + function MyFoo() { + return _super !== null && _super.apply(this, arguments) || this; + } + return MyFoo; +}(library_1.Foo)); +exports.MyFoo = MyFoo; +//// [typed_component.js] +"use strict"; +var __extends = (this && this.__extends) || (function () { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return function (d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +exports.__esModule = true; +var component_1 = require("./component"); +var TypedFoo = /** @class */ (function (_super) { + __extends(TypedFoo, _super); + function TypedFoo() { + var _this = _super.call(this, { x: "string", y: 42 }, { value: undefined }) || this; + _this.props.x; + _this.props.y; + _this.state.value; + _this.member; + return _this; + } + return TypedFoo; +}(component_1.MyFoo)); +exports.TypedFoo = TypedFoo; diff --git a/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.symbols b/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.symbols new file mode 100644 index 00000000000..ba18a4ecca9 --- /dev/null +++ b/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.symbols @@ -0,0 +1,70 @@ +=== tests/cases/compiler/library.d.ts === +export class Foo { +>Foo : Symbol(Foo, Decl(library.d.ts, --, --)) +>T : Symbol(T, Decl(library.d.ts, --, --)) +>U : Symbol(U, Decl(library.d.ts, --, --)) + + props: T; +>props : Symbol(Foo.props, Decl(library.d.ts, --, --)) +>T : Symbol(T, Decl(library.d.ts, --, --)) + + state: U; +>state : Symbol(Foo.state, Decl(library.d.ts, --, --)) +>U : Symbol(U, Decl(library.d.ts, --, --)) + + constructor(props: T, state: U); +>props : Symbol(props, Decl(library.d.ts, --, --)) +>T : Symbol(T, Decl(library.d.ts, --, --)) +>state : Symbol(state, Decl(library.d.ts, --, --)) +>U : Symbol(U, Decl(library.d.ts, --, --)) +} + +=== tests/cases/compiler/component.js === +import { Foo } from "./library"; +>Foo : Symbol(Foo, Decl(component.js, 0, 8)) + +export class MyFoo extends Foo { +>MyFoo : Symbol(MyFoo, Decl(component.js, 0, 32)) +>Foo : Symbol(Foo, Decl(component.js, 0, 8)) + + member; +>member : Symbol(MyFoo.member, Decl(component.js, 1, 32)) +} + +=== tests/cases/compiler/typed_component.ts === +import { MyFoo } from "./component"; +>MyFoo : Symbol(MyFoo, Decl(typed_component.ts, 0, 8)) + +export class TypedFoo extends MyFoo { +>TypedFoo : Symbol(TypedFoo, Decl(typed_component.ts, 0, 36)) +>MyFoo : Symbol(MyFoo, Decl(typed_component.ts, 0, 8)) + + constructor() { + super({x: "string", y: 42}, { value: undefined }); +>super : Symbol(MyFoo, Decl(component.js, 0, 32)) +>x : Symbol(x, Decl(typed_component.ts, 3, 15)) +>y : Symbol(y, Decl(typed_component.ts, 3, 27)) +>value : Symbol(value, Decl(typed_component.ts, 3, 37)) +>undefined : Symbol(undefined) + + this.props.x; +>this.props : Symbol(Foo.props, Decl(library.d.ts, --, --)) +>this : Symbol(TypedFoo, Decl(typed_component.ts, 0, 36)) +>props : Symbol(Foo.props, Decl(library.d.ts, --, --)) + + this.props.y; +>this.props : Symbol(Foo.props, Decl(library.d.ts, --, --)) +>this : Symbol(TypedFoo, Decl(typed_component.ts, 0, 36)) +>props : Symbol(Foo.props, Decl(library.d.ts, --, --)) + + this.state.value; +>this.state : Symbol(Foo.state, Decl(library.d.ts, --, --)) +>this : Symbol(TypedFoo, Decl(typed_component.ts, 0, 36)) +>state : Symbol(Foo.state, Decl(library.d.ts, --, --)) + + this.member; +>this.member : Symbol(MyFoo.member, Decl(component.js, 1, 32)) +>this : Symbol(TypedFoo, Decl(typed_component.ts, 0, 36)) +>member : Symbol(MyFoo.member, Decl(component.js, 1, 32)) + } +} diff --git a/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.types b/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.types new file mode 100644 index 00000000000..4e4bab57696 --- /dev/null +++ b/tests/baselines/reference/defaultPropsEmptyCurlyBecomesAnyForJs.types @@ -0,0 +1,81 @@ +=== tests/cases/compiler/library.d.ts === +export class Foo { +>Foo : Foo +>T : T +>U : U + + props: T; +>props : T +>T : T + + state: U; +>state : U +>U : U + + constructor(props: T, state: U); +>props : T +>T : T +>state : U +>U : U +} + +=== tests/cases/compiler/component.js === +import { Foo } from "./library"; +>Foo : typeof Foo + +export class MyFoo extends Foo { +>MyFoo : MyFoo +>Foo : Foo + + member; +>member : any +} + +=== tests/cases/compiler/typed_component.ts === +import { MyFoo } from "./component"; +>MyFoo : typeof MyFoo + +export class TypedFoo extends MyFoo { +>TypedFoo : TypedFoo +>MyFoo : MyFoo + + constructor() { + super({x: "string", y: 42}, { value: undefined }); +>super({x: "string", y: 42}, { value: undefined }) : void +>super : typeof MyFoo +>{x: "string", y: 42} : { x: string; y: number; } +>x : string +>"string" : "string" +>y : number +>42 : 42 +>{ value: undefined } : { value: undefined; } +>value : undefined +>undefined : undefined + + this.props.x; +>this.props.x : any +>this.props : any +>this : this +>props : any +>x : any + + this.props.y; +>this.props.y : any +>this.props : any +>this : this +>props : any +>y : any + + this.state.value; +>this.state.value : any +>this.state : any +>this : this +>state : any +>value : any + + this.member; +>this.member : any +>this : this +>member : any + } +} diff --git a/tests/cases/compiler/defaultPropsEmptyCurlyBecomesAnyForJs.ts b/tests/cases/compiler/defaultPropsEmptyCurlyBecomesAnyForJs.ts new file mode 100644 index 00000000000..2375ed2a5ba --- /dev/null +++ b/tests/cases/compiler/defaultPropsEmptyCurlyBecomesAnyForJs.ts @@ -0,0 +1,26 @@ +// @allowJs: true +// @outDir: ./built +// @filename: library.d.ts +export class Foo { + props: T; + state: U; + constructor(props: T, state: U); +} + +// @filename: component.js +import { Foo } from "./library"; +export class MyFoo extends Foo { + member; +} + +// @filename: typed_component.ts +import { MyFoo } from "./component"; +export class TypedFoo extends MyFoo { + constructor() { + super({x: "string", y: 42}, { value: undefined }); + this.props.x; + this.props.y; + this.state.value; + this.member; + } +} \ No newline at end of file