Creating an extendable typescript package based on Koa with default and named exports
I am creating a module that extends Koa and adds some basic functionality, while still being extendable by the consumers of the package. This is proving to be very challenging so I hope someone has an idea on how this can be done.
End goal is to be able to retain types while using my package like this:
// Note default and named export - I have also tried only having named exports
import MyKoa, isAuth from 'mykoa';
import Router from 'koa-router';
// How I try to augment MyKoa in the consumer apps
declare module 'mykoa'
// Doesn't work: cannot use namespace "MyKoa" as value
namespace MyKoa
interface Options
isReady: boolean;
// Doesn't work at all
interface Options
isReady: boolean;
const app = new MyKoa();
const router = new Router();
router.get('/', isAuth(), ctx =>
ctx.body = ctx.app.options.isReady; // Typescript should know that (ctx.)app.options.isReady is a boolean
);
app.use(router.routes());
app.listen(3000);
Currently I have 2 files:
src/lib/MyKoa.ts:
import Koa from 'koa';
// Augment Koa
declare module 'koa'
interface Application extends MyKoa // This ensures that MyKoa types are retained in koa-router middleware and works fine
// My Koa class
class MyKoa extends Koa
public options: MyKoa.Options = ;
// Declare MyKoa namespace to hold relevant types
declare namespace MyKoa
interface Options
export = MyKoa;
src/index.ts:
import MyKoa from './lib/MyKoa';
import isAuth from './lib/isAuth';
export default MyKoa;
export isAuth ;
I can extend the types fine if I declare the module with full path to the files (e.g. mykoa/dist/lib/MyKoa), but I don't want the consumer of the package to rely on the internal directory structure of my package. Is this even possible? Is there a better way of providing the same functionality?
typescript
add a comment |
I am creating a module that extends Koa and adds some basic functionality, while still being extendable by the consumers of the package. This is proving to be very challenging so I hope someone has an idea on how this can be done.
End goal is to be able to retain types while using my package like this:
// Note default and named export - I have also tried only having named exports
import MyKoa, isAuth from 'mykoa';
import Router from 'koa-router';
// How I try to augment MyKoa in the consumer apps
declare module 'mykoa'
// Doesn't work: cannot use namespace "MyKoa" as value
namespace MyKoa
interface Options
isReady: boolean;
// Doesn't work at all
interface Options
isReady: boolean;
const app = new MyKoa();
const router = new Router();
router.get('/', isAuth(), ctx =>
ctx.body = ctx.app.options.isReady; // Typescript should know that (ctx.)app.options.isReady is a boolean
);
app.use(router.routes());
app.listen(3000);
Currently I have 2 files:
src/lib/MyKoa.ts:
import Koa from 'koa';
// Augment Koa
declare module 'koa'
interface Application extends MyKoa // This ensures that MyKoa types are retained in koa-router middleware and works fine
// My Koa class
class MyKoa extends Koa
public options: MyKoa.Options = ;
// Declare MyKoa namespace to hold relevant types
declare namespace MyKoa
interface Options
export = MyKoa;
src/index.ts:
import MyKoa from './lib/MyKoa';
import isAuth from './lib/isAuth';
export default MyKoa;
export isAuth ;
I can extend the types fine if I declare the module with full path to the files (e.g. mykoa/dist/lib/MyKoa), but I don't want the consumer of the package to rely on the internal directory structure of my package. Is this even possible? Is there a better way of providing the same functionality?
typescript
add a comment |
I am creating a module that extends Koa and adds some basic functionality, while still being extendable by the consumers of the package. This is proving to be very challenging so I hope someone has an idea on how this can be done.
End goal is to be able to retain types while using my package like this:
// Note default and named export - I have also tried only having named exports
import MyKoa, isAuth from 'mykoa';
import Router from 'koa-router';
// How I try to augment MyKoa in the consumer apps
declare module 'mykoa'
// Doesn't work: cannot use namespace "MyKoa" as value
namespace MyKoa
interface Options
isReady: boolean;
// Doesn't work at all
interface Options
isReady: boolean;
const app = new MyKoa();
const router = new Router();
router.get('/', isAuth(), ctx =>
ctx.body = ctx.app.options.isReady; // Typescript should know that (ctx.)app.options.isReady is a boolean
);
app.use(router.routes());
app.listen(3000);
Currently I have 2 files:
src/lib/MyKoa.ts:
import Koa from 'koa';
// Augment Koa
declare module 'koa'
interface Application extends MyKoa // This ensures that MyKoa types are retained in koa-router middleware and works fine
// My Koa class
class MyKoa extends Koa
public options: MyKoa.Options = ;
// Declare MyKoa namespace to hold relevant types
declare namespace MyKoa
interface Options
export = MyKoa;
src/index.ts:
import MyKoa from './lib/MyKoa';
import isAuth from './lib/isAuth';
export default MyKoa;
export isAuth ;
I can extend the types fine if I declare the module with full path to the files (e.g. mykoa/dist/lib/MyKoa), but I don't want the consumer of the package to rely on the internal directory structure of my package. Is this even possible? Is there a better way of providing the same functionality?
typescript
I am creating a module that extends Koa and adds some basic functionality, while still being extendable by the consumers of the package. This is proving to be very challenging so I hope someone has an idea on how this can be done.
End goal is to be able to retain types while using my package like this:
// Note default and named export - I have also tried only having named exports
import MyKoa, isAuth from 'mykoa';
import Router from 'koa-router';
// How I try to augment MyKoa in the consumer apps
declare module 'mykoa'
// Doesn't work: cannot use namespace "MyKoa" as value
namespace MyKoa
interface Options
isReady: boolean;
// Doesn't work at all
interface Options
isReady: boolean;
const app = new MyKoa();
const router = new Router();
router.get('/', isAuth(), ctx =>
ctx.body = ctx.app.options.isReady; // Typescript should know that (ctx.)app.options.isReady is a boolean
);
app.use(router.routes());
app.listen(3000);
Currently I have 2 files:
src/lib/MyKoa.ts:
import Koa from 'koa';
// Augment Koa
declare module 'koa'
interface Application extends MyKoa // This ensures that MyKoa types are retained in koa-router middleware and works fine
// My Koa class
class MyKoa extends Koa
public options: MyKoa.Options = ;
// Declare MyKoa namespace to hold relevant types
declare namespace MyKoa
interface Options
export = MyKoa;
src/index.ts:
import MyKoa from './lib/MyKoa';
import isAuth from './lib/isAuth';
export default MyKoa;
export isAuth ;
I can extend the types fine if I declare the module with full path to the files (e.g. mykoa/dist/lib/MyKoa), but I don't want the consumer of the package to rely on the internal directory structure of my package. Is this even possible? Is there a better way of providing the same functionality?
typescript
typescript
asked Nov 12 '18 at 14:09
chredv12chredv12
31
31
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
The requirement for augmentations of a symbol to target the module that originally defines it and not a module that re-exports it is a current known limitation of TypeScript. The only workaround I can suggest is to move the symbols that you intend consumers of mykoa
to augment into the main module of mykoa
.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53263917%2fcreating-an-extendable-typescript-package-based-on-koa-with-default-and-named-ex%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The requirement for augmentations of a symbol to target the module that originally defines it and not a module that re-exports it is a current known limitation of TypeScript. The only workaround I can suggest is to move the symbols that you intend consumers of mykoa
to augment into the main module of mykoa
.
add a comment |
The requirement for augmentations of a symbol to target the module that originally defines it and not a module that re-exports it is a current known limitation of TypeScript. The only workaround I can suggest is to move the symbols that you intend consumers of mykoa
to augment into the main module of mykoa
.
add a comment |
The requirement for augmentations of a symbol to target the module that originally defines it and not a module that re-exports it is a current known limitation of TypeScript. The only workaround I can suggest is to move the symbols that you intend consumers of mykoa
to augment into the main module of mykoa
.
The requirement for augmentations of a symbol to target the module that originally defines it and not a module that re-exports it is a current known limitation of TypeScript. The only workaround I can suggest is to move the symbols that you intend consumers of mykoa
to augment into the main module of mykoa
.
answered Nov 12 '18 at 21:11
Matt McCutchenMatt McCutchen
13.4k719
13.4k719
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53263917%2fcreating-an-extendable-typescript-package-based-on-koa-with-default-and-named-ex%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown