Skip to content

Declaration emit includes function properties#26499

Merged
sandersn merged 6 commits into
masterfrom
declaration-emit-function-properties
Aug 27, 2018
Merged

Declaration emit includes function properties#26499
sandersn merged 6 commits into
masterfrom
declaration-emit-function-properties

Conversation

@sandersn
Copy link
Copy Markdown
Member

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

function f() { }
f.p = 1

Appears in a d.ts as

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.

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.

Fixes #26485

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.
@sandersn
Copy link
Copy Markdown
Member Author

@weswigham Any opinions on the right approach here?

I was about to try the namespace merge, but I realised that I don't know how to make transformTopLevelDeclaration return two declarations.

@weswigham
Copy link
Copy Markdown
Member

I was about to try the namespace merge, but I realised that I don't know how to make transformTopLevelDeclaration return two declarations.

Returning two declarations in an array should be sufficient. A VisitResult is either a T, an undefined, or an array of T.

// Generators lose their generator-ness, excepting their return type
if (resolver.isJSContainerFunctionDeclaration(input)) {
const varDecl = createVariableDeclaration(input.name!, resolver.createTypeOfDeclaration(input, enclosingDeclaration, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const statement = createVariableStatement(needsDeclare ? [createModifier(SyntaxKind.DeclareKeyword)] : [], createVariableDeclarationList([varDecl], NodeFlags.Const));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd use ensureModifiers(input) instead of the needsDeclare check here.

const varDecl = createVariableDeclaration(unescapeLeadingUnderscores(p.escapedName), type, /*initializer*/ undefined);
return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([varDecl]));
});
const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, createModuleBlock(declarations), NodeFlags.Namespace);
Copy link
Copy Markdown
Member

@weswigham weswigham Aug 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably needs to be ensureModifiers(input, isPrivate) to inherit the scope's privacy correctly.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matters with a case like

namespace Foo {
  function bar(): void {}
  bar.num = 42;
  export function foo() {
    return bar;
  }
}

@sandersn
Copy link
Copy Markdown
Member Author

@weswigham mind taking a look at the latest commit? I added your example, but the output looks wrong to me — I expected to see an object literal type, not typeof ExpandoNamespace, for the type of a expando function that's not exported.

@weswigham
Copy link
Copy Markdown
Member

Nope, it's perfect. The name shows up because it's visible internally at that location, which is all that matters.

@sandersn sandersn merged commit 6419240 into master Aug 27, 2018
@sandersn sandersn deleted the declaration-emit-function-properties branch August 27, 2018 17:29
@microsoft microsoft locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants