javascript - How do I use namespaces with TypeScript external modules? -
i have code:
basetypes.ts
export module living.things { export class animal { move() { /* ... */ } } export class plant { photosynthesize() { /* ... */ } } } dog.ts
import b = require('./basetypes'); export module living.things { // error, can't find name 'animal', ?? export class dog extends animal { woof() { } } } tree.ts
// error, can't use same name twice, ?? import b = require('./basetypes'); import b = require('./dogs'); module living.things { // why have write b.living.things.plant instead of b.plant?? class tree extends b.living.things.plant { } } this confusing. want have bunch of external modules contribute types same namespace, living.things. seems doesn't work @ -- can't see animal in dogs.ts. have write full namespace name b.living.things.plant in tree.ts. doesn't work combine multiple objects in same namespace across file. how do this?
candy cup analogy
version 1: cup every candy
let's wrote code this:
mod1.ts
export namespace { export class twix { ... } } mod2.ts
export namespace { export class peanutbuttercup { ... } } mod3.ts
export namespace { export class kitkat { ... } } each module (sheet of paper) gets its own cup named a. useless - you're not organizing candy here, you're adding additional step (taking out of cup) between , treats.
version 2: 1 cup in global scope
if weren't using modules, might write code (note lack of export declarations):
global1.ts
namespace { export class twix { ... } } global2.ts
namespace { export class peanutbuttercup { ... } } global3.ts
namespace { export class kitkat { ... } } this code creates merged namespace a in global scope:
this setup useful, doesn't apply in case of modules (because modules don't pollute global scope).
version 3: going cupless
going original example, cups a, a, , a aren't doing favors. instead, write code as:
mod1.ts
export class twix { ... } mod2.ts
export class peanutbuttercup { ... } mod3.ts
export class kitkat { ... } to create picture looks this:
much better!
now, if you're still thinking how want use namespace modules, read on...
these aren't concepts you're looking for
we need go origins of why namespaces exist in first place , examine whether reasons make sense external modules.
organization: namespaces handy grouping logically-related objects , types. example, in c#, you're going find collection types in system.collections. organizing our types hierarchical namespaces, provide "discovery" experience users of types.
name conflicts: namespaces important avoid naming collisions. example, might have my.application.customer.addform , my.application.order.addform -- 2 types same name, different namespace. in language identifiers exist in same root scope , assemblies load types, it's critical have in namespace.
do reasons make sense in external modules?
organization: external modules present in file system, necessarily. have resolve them path , filename, there's logical organization scheme use. can have /collections/generic/ folder list module in it.
name conflicts: doesn't apply @ in external modules. within module, there's no plausible reason have 2 objects same name. consumption side, consumer of given module gets pick name use refer module, accidental naming conflicts impossible.
even if don't believe reasons adequately addressed how modules work, "solution" of trying use namespaces in external modules doesn't work.
boxes in boxes in boxes
a story:
your friend bob calls up. "i have great new organization scheme in house", says, "come check out!". neat, let's go see bob has come with.
you start in kitchen , open pantry. there 60 different boxes, each labelled "pantry". pick box @ random , open it. inside single box labelled "grains". open "grains" box , find single box labelled "pasta". open "pasta" box , find single box labelled "penne". open box , find, expect, bag of penne pasta.
slightly confused, pick adjacent box, labelled "pantry". inside single box, again labelled "grains". open "grains" box and, again, find single box labelled "pasta". open "pasta" box , find single box, 1 labelled "rigatoni". open box , find... bag of rigatoni pasta.
"it's great!" says bob. "everything in namespace!".
"but bob..." reply. "your organization scheme useless. have open bunch of boxes anything, , it's not more convenient find if had put in one box instead of three. in fact, since pantry sorted shelf-by-shelf, don't need boxes @ all. why not set pasta on shelf , pick when need it?"
"you don't understand -- need make sure no 1 else puts doesn't belong in 'pantry' namespace. , i've safely organized pasta
pantry.grains.pastanamespace can find it"bob confused man.
modules own box
you've had similar happen in real life: order few things on amazon, , each item shows in own box, smaller box inside, item wrapped in own packaging. if interior boxes similar, shipments not usefully "combined".
going box analogy, key observation external modules own box. might complex item lots of functionality, given external module own box.
guidance external modules
now we've figured out don't need use 'namespaces', how should organize our modules? guiding principles , examples follow.
export close top-level possible
- if you're exporting single class or function, use
export default:
myclass.ts
export default class sometype { constructor() { ... } } myfunc.ts
function getthing() { return 'thing'; } export default getthing; consumption
import t './myclass'; import f './myfunc'; var x = new t(); console.log(f()); this optimal consumers. can name type whatever want (t in case) , don't have extraneous dotting find objects.
- if you're exporting multiple objects, put them @ top-level:
mythings.ts
export class sometype { /* ... */ } export function somefunc() { /* ... */ } consumption
import * m './mythings'; var x = new m.sometype(); var y = m.somefunc(); - if you're exporting large number of things, should use
module/namespacekeyword:
mylargemodule.ts
export namespace animals { export class dog { ... } export class cat { ... } } export namepsace plants { export class tree { ... } } consumption
import { animals, plants} './mylargemodule'; var x = new animals.dog(); red flags
all of following red flags module structuring. double-check you're not trying namespace external modules if of these apply files:
- a file top-level declaration
export module foo { ... }(removefoo, move 'up' level) - a file has single
export classorexport functionisn'texport default - multiple files have same
export module foo {@ top-level (don't think these going combine 1foo!)



Comments
Post a Comment