-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Closed
Labels
Design NotesNotes from our design meetingsNotes from our design meetings
Description
N.B. these notes use the word "module" extensively, which we now use to only mean "external module" in the old parlance. I will use "namespace" to refer to "internal modules" if needed.
Augmenting Types from External Modules (#5269, #4166)
- Bind operator is like extension methods for JS
- But people do love
. - And if you love
.., prototype mutation is the only way to accomplish it
- But people do love
- Two problems facing Rx
- How do I make a class appear to have methods that I don't want to implement
- Remove the check for ambientness of classes merged with interfaces (:+1:)
- How do I make the type of a global (or module-scoped) type depend on the set of modules that are imported?
- This is an anti-pattern, but what can you do ¯_(ツ)_/¯
- Some very terrible workarounds exist
- Implementation approach
- Binder has a concept of 'scripts' which contribute to the global, and 'modules' which contribute to their local scope, along with their separate exports
- Only ambient modules have a symbol in the global scope, which is their quoted name
- Module files never get a symbol and are not subject to merging; this is what we would need to change
- Fix: add a canonical name to all module files so that they become mergable
- This gets us augmentation of modules even from within other modules, which is currently disallowed
- Q: How do you augment global types in this model?
- A: We have a special string that means the global scope, use e.g.
declare module '/' {ordeclare module '' {
- A: We have a special string that means the global scope, use e.g.
- Note that the types in a module would not directly visible in an interior ambient module declaration
- Add an
importdeclaration? It's weird. Maybe implicitly import them into scope... try it out and see what happens, should be OK
- Add an
- Q: How do we resolve these names?
- A: Relative to the current file
- Q: How do we produce these canonical names?
- A: Need to figure that out. Doable.
- Q: How do I refer to shadowed global types from within an ambient module inside a module?
- A: Maybe you just don't... or refer to
"./obs".Observable - A: Or `import { Observable } from './obs';
- A: Or
global.Arrayin the global case? - A: Or
interface obs.Observable<T> { ... }<- nice
- A: Maybe you just don't... or refer to
- Theory that
interface foo.bar { }always means extendingbarfrom thefoonamespace- With special LHS semantics for
global - Can I declare things here, too?
- Yes
- With special LHS semantics for
- Syntax/semantics:
interface global::Foo,interface global.Foo,interface global Foo, ?declare global var x;declare in './obs' var x;- What happens if I try to
declare ina non-existent module?- It's like an ambient external module?
- Only ambient classes could use dotted declarations
- Speculation that we could emit non-ambient classes this way
- 👍 Conclusions
- Allow merging of interfaces and non-ambient classes
declare module 'foo' {is allowed in modules- Are the containing module's symbols in scope? Yes, and the global symbols have priority
declare module '../relativePath' {is allowed in a module, but not in a script- Are the containing module's symbols in scope? Yes
declare global {augments the gloal scope, and is only allowed at top-level in a module (not a script)- Are module
imports allowed in here? No. - Is
export =allowed in here? No. - Are the containing module's symbols in scope? Yes
- Are module
- Rabble about declaration emitter
- Vlad and Anders to tackle it
- How do I make a class appear to have methods that I don't want to implement
Metadata
Metadata
Assignees
Labels
Design NotesNotes from our design meetingsNotes from our design meetings