FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

initial revision of external module augmentations by vladima · Pull Request #6213 · microsoft/TypeScript · GitHub

initial revision of external module augmentations - #6213

Merged
Vladimir Matveev (vladima) merged 10 commits into
masterfrom
moduleAugmentations
Jan 16, 2016
Merged

initial revision of external module augmentations#6213
Vladimir Matveev (vladima) merged 10 commits into
masterfrom
moduleAugmentations

Conversation

Copy link
Copy Markdown
Contributor

Module augmentation is a declaration of ambient module that directly nested either in external module or in top level ambient external module.
Name of module augmentation is resolved using the same set of rules as module specifiers in import \ export declarations.
If name is successfully resolved to some external module then declarations in module augmentation are merged with declarations inside module using standard rules for declaration merging.
Module augmentations cannot add new items to the top level scope but rather patch existing declarations.

for example

// observable.ts
export class Observable<T> {}
// map.ts
import {Observable} from "./observable";
Observable.prototype.map = function () { /* ... */ }

declare module "./observable" {
    interface Observable<T> {
        map<U>(proj: (el: T) => U): Observable<U>;
    }
}
// consumer.ts
import {Observable} from "./observable";
import "./map";
let o: Observable<number>;
o.map(x => x.toFixed());

Here module map can declare that internally it will patch Observable type and add map function to it.

Fixes: #5269, #6022

Pending work:

  • - add syntactic support for augmenting global scope. Currently augmentation for the global scope is defined as ambient module with special name "/" but this is just a placeholder. The version that we ended up during the design meeting was:
// in external module
export {};
declare global {}

or

// in script file
declare module "array" {
    global {}
}

Comment thread src/compiler/binder.ts Outdated

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I don't see this getting used anywhere apart from the later assignment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

right, forgot to remove that. Thanks

Comment thread src/compiler/checker.ts Outdated

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

isGlobalAugmentation or augmentsGlobal

Copy link
Copy Markdown
Member

What exactly is the recommended way to augment a default export? Is it possible in this implementation?

Copy link
Copy Markdown
Contributor Author

it is not possible

Copy link
Copy Markdown
Member

This also appears to take care of #2784. You might want to take note and give a heads up on that issue when this goes in.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

what about external modules with no exports or no module augmentation? soemthing like:

import {a} from "./mod";
// do something with a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

i thought we will do this for any external module, that we never emitted any import, export, or module augmentation for.

Copy link
Copy Markdown
Contributor

👍

Comment thread src/compiler/checker.ts Outdated

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This should be checkModuleAugmentationElement. It checks and element in the body, not the body itself.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Copy link
Copy Markdown
Contributor Author

build failure is related to #6478

Copy link
Copy Markdown
Contributor Author

Anders Hejlsberg (@ahejlsberg) done, do you have any other comments?

Comment thread src/compiler/checker.ts

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The error message below seems a bit odd for this case, but maybe it's fine.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

for global case we can easily lift this restriction since it is possible to add new entries to global scope from within a module. Currently the fact that we have it is only because of consistency in behavior for augmentations.

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

No sure I understand, maybe we're talking about different issues. This code is saying that you get an error when you have an exported member in a global augmentation block, right? I'm thinking it should never be valid to use export in a global augmentation block.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

the idea of this check is following: symbol.parent will be undefined if symbol was initially defined in the global scope. If symbol.parent is not undefined this means that this symbol was declared inside augmentation and will declare new entry in the global scope which is disallowed in current design

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

If symbol.parent is not undefined this means that this symbol was declared inside augmentation

Why is that so? symbol.parent is non-undefined when the symbol is exported, but it might still be declared inside the augmentation. I'm not getting this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

symbols whose initial declaration is in global scope are never exported and symbol.parent for them is always undefined. if symbol.parent !== undefined this means that this symbol is exported from somewhere and as a consequence initially defined in augmentation not in global scope

Copy link
Copy Markdown
Contributor

In map.ts: since the ambient module declaration advertises to the compiler that Observable<T> has a map member, would you be able to attach a function of the appropriate kind to the prototype without casting to <any>?

Comment thread src/compiler/checker.ts Outdated

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I have a hard time reasoning about this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

this assert is redundant. it basically says: augmentation can only change exported symbol (parent !== undefeind) that really has a declaration (not a virtual symbol like prototype) - this should always be the case. I'll remove it

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

So did you mean symbol.valueDeclaration !== undefined? You currently have symbol.parent.valueDeclaration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

symbol.parent.valueDeclaration - is an augmentation: declare module .... symbol.valueDeclaration is declaration inside the augmentation. Currently we report error if container that this symbol is module augmentation and not a normal external module

Copy link
Copy Markdown

Awesome! Great stuff. Thank you!

Copy link
Copy Markdown
Member

🎉 👏 👏 👏 👏 👏 👏 👏

Copy link
Copy Markdown
Member

👍

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.

Type generation for "modularly designed" libraries is hard

9 participants


Back | FazBrowse Home | New Git URL