TypeScript/tests/cases/conformance/salsa/typeFromPropertyAssignment29.ts
Nathan Shively-Sanders 6419240ab2
Declaration emit includes function properties (#26499)
* Declaration emit includes function properties

It does this by printing the type as an object literal type:

```ts
function f() { }
f.p = 1
```

Appears in a d.ts as

```ts
declare var f: {
  (): void;
  p: number;
}
```

It would also be possible to represent it as a namespace merge. I'm not
sure which is better.

```ts
declare function f(): void;
declare namespace f {
  export var p: number;
}
```

In order to avoid a private-name-used error (though I think it was
actually *unused*), I also had to change the nodeBuilder code to match.
This is arguably harder to read. So it's possible that I should instead
keep the nodeBuilder version as `typeof f` and make an exception for
private name use.

* Emit namespace merge instead of object type

This makes the change smaller, overall.

* Fix isJSContainerFunctionDeclaration+namespace merges

Also improve emit style to match other namespace emit.

* Add isPrivate + test case from PR comments
2018-08-27 10:29:53 -07:00

87 lines
2 KiB
TypeScript

// @declaration: true
function ExpandoDecl(n: number) {
return n.toString();
}
ExpandoDecl.prop = 2
ExpandoDecl.m = function(n: number) {
return n + 1;
}
var n = ExpandoDecl.prop + ExpandoDecl.m(12) + ExpandoDecl(101).length
const ExpandoExpr = function (n: number) {
return n.toString();
}
ExpandoExpr.prop = { x: 2 }
ExpandoExpr.prop = { y: "" }
ExpandoExpr.m = function(n: number) {
return n + 1;
}
var n = (ExpandoExpr.prop.x || 0) + ExpandoExpr.m(12) + ExpandoExpr(101).length
const ExpandoArrow = (n: number) => n.toString();
ExpandoArrow.prop = 2
ExpandoArrow.m = function(n: number) {
return n + 1;
}
function ExpandoNested(n: number) {
const nested = function (m: number) {
return n + m;
};
nested.total = n + 1_000_000;
return nested;
}
ExpandoNested.also = -1;
function ExpandoMerge(n: number) {
return n * 100;
}
ExpandoMerge.p1 = 111
namespace ExpandoMerge {
export var p2 = 222;
}
namespace ExpandoMerge {
export var p3 = 333;
}
var n = ExpandoMerge.p1 + ExpandoMerge.p2 + ExpandoMerge.p3 + ExpandoMerge(1);
namespace Ns {
function ExpandoNamespace(): void {}
ExpandoNamespace.p6 = 42;
export function foo() {
return ExpandoNamespace;
}
}
// Should not work in Typescript -- must be const
var ExpandoExpr2 = function (n: number) {
return n.toString();
}
ExpandoExpr2.prop = 2
ExpandoExpr2.m = function(n: number) {
return n + 1;
}
var n = ExpandoExpr2.prop + ExpandoExpr2.m(12) + ExpandoExpr2(101).length
// Should not work in typescript -- classes already have statics
class ExpandoClass {
n = 1001;
}
ExpandoClass.prop = 2
ExpandoClass.m = function(n: number) {
return n + 1;
}
var n = ExpandoClass.prop + ExpandoClass.m(12) + new ExpandoClass().n
// Class expressions shouldn't work in typescript either
var ExpandoExpr3 = class {
n = 10001;
}
ExpandoExpr3.prop = 3
ExpandoExpr3.m = function(n: number) {
return n + 1;
}
var n = ExpandoExpr3.prop + ExpandoExpr3.m(13) + new ExpandoExpr3().n