-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can not declaration merging for default exported class #14080
Comments
If I write both export Foo and export default Foo in Foo.ts, its works (both import Foo and import {Foo} works)
|
You can only augment "exported" declarations. Class It just happens that The TS compiler needs to allow |
Could this be related to an old bug? #2537 |
@Zaibot this feature (module augmentation) did not exist back then. So no. |
Sorry, misread or mixed up the thread |
Would fixing this address my problem with defining inner classes and interfaces on a default export? I get "Merged declaration 'Outer' cannot include a default export declaration." mymodule.ts:
myconsumer.ts:
I'm trying to keep my consumer code succinct, so I don't have code like:
(Actually, my preference is to do this with an inner interface in my particular situation, but I can't get it to work with an inner class either.) (Also, in my case, static methods on subclasses of Outer produce the Inner instances, for use by external classes in characterizing instances of the Outer subclasses.) |
My interim solution is to move the inner class out to its own module. I can give it a reasonable import name and still keep class references succinct. I guess I don't really need inner classes and interfaces. |
P.S. How did I automatically unassign @yuit? |
Ugh. Here's a prevalent use case for nested interfaces:
Except you can't do it yet on default exports. Are people using a different pattern? Just not using default exports? |
I've stopped using default exports in most cases - partly due to this, and
also to make refactoring less painful
…On Thu, Sep 28, 2017, 10:49 Joe Lapp ***@***.***> wrote:
Ugh. Here's a prevalent use case for nested interfaces:
export default class MyController {
constructor(options?: Options) {
//...
}
}
namespace MyController {
export interface Options {
//...
}
}
Except you can't do it yet on default exports.
Are people using a different pattern? Just not using default exports?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#14080 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAChnSJ6MAONZ-j5pwNsuxcaos8l6rNsks5sm9wpgaJpZM4MBduT>
.
|
Thanks @nevir. Is the issue with defaults and refactoring that a class is less likely to have a single name across the entire application? Is that also an argument for not exporting functions directly but instead making stateless functions static methods on exported classes? |
Any time you export a default, you're effectively creating a new name - so
if you want to rename something globally, you have to search/replace for
it, and track all the imports that re-export it. But by sticking to named
exports, various refactoring tools can follow that name all the way through
the code base 👍
…On Fri, Sep 29, 2017 at 12:57 PM Joe Lapp ***@***.***> wrote:
Thanks @nevir <https://github.com/nevir>. Is the issue with defaults and
refactoring that a class is less likely to have a single name across the
entire application? Is that also an argument for not exporting functions
directly but instead making stateless functions static methods on exported
classes?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#14080 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAChnR1J5GO4IAiJhnQGefZc5XcMO-WJks5snUu-gaJpZM4MBduT>
.
|
I wanted to point out that I think export-assigned ( |
Is going to get fixed anytime soon? It makes correctly typing some modules, eg. // @types/markdown-it
declare module 'markdown-it'
{
interface MarkdownItStatic
{
new (): MarkdownIt;
(): MarkdownIt;
render(s: string): string;
}
let MarkdownIt: MarkdownItStatic;
namespace MarkdownIt {
export interface State { /* ... */ }
/* ... */
}
export default MarkdownIt;
} // @types/markdown-it-incremental-dom
import * as MD from 'markdown-it';
declare module 'markdown-it'
{
// Idea #1 (failed)
interface MarkdownItStatic
{
renderToIncrementalDOM(): void;
}
let default: MarkdownItStatic;
// Idea #2 (failed)
declare default.renderToIncrementalDOM(): void;
// Idea #3 (failed)
interface MarkdownItStatic
{
renderToIncrementalDOM(): void;
}
// Idea #4 (failed)
const default:
{
renderToIncrementalDOM(): void
}
} EDIT: I just realized that |
@m93a I don't think your scenario has anything to do with this issue since you aren't using a class. Your idea 3 works if I |
Is there a way for augmenting a module exported with i.e knex.d.ts interface Knex {
test1: string;
}
export = Knex; file.ts declare module 'knex' {
interface Knex {
test2: string;
}
} |
node_modules -> knex.ts interface Knex {
test1: string;
}
export = Knex; custom knex.ts import $knex from "knex";
const knex = $knex as typeof $knex & {
test2: string;
}
export default knex; |
I just figured out a workaround for this while trying to augment node_modules @types/chart.js/index.d.ts declare class Chart { ... }
declare namespace Chart { ... }
export = Chart;
export as namespace Chart; my-typings.d.ts import * as Chart from 'chart.js';
declare global {
interface Chart {
panZoom: (increment: number) => void;
}
} usage in my-file.ts import * as Chart from 'chart.js';
const chart = new Chart({...});
chart.panZoom(5); I don't know exactly why, but it works even if in my file I import as a different name I haven't tested if this also works with default exports. Here is the PR that I made for the chart.js augmentation DefinitelyTyped/DefinitelyTyped#44519 |
Was going a bit insane trying to figure our what was happening. Here's a small reproducible: /** @typedef {import('stream').Readable} */
/** @typedef {import('stream').Writable} Writable */
export default class MyClassName {
}
That's because |
It seems to be working with the following convoluted setup: some-library-you-cant-modify/Foo.ts // This is the original class. You can't augment it directly because it's a default export.
export default class Foo {
existingProperty: number;
} my-library/typings/Foo.ts import Foo from 'some-library-you-cant-modify/Foo'
// just reexporting the same class, but this time it's not a default export
export { Foo }; my-library/typings/Foo.d.ts import { Foo } from './Foo';
declare module './Foo' {
interface Foo {
myProperty: string; // class Foo is now augmented with this added property
}
} my-library/consumer.ts // Notice I'm importing from the original library, it works fine anyway.
// This means you don't have to update any existing code.
import Foo from 'some-library-you-cant-modify/Foo';
let foo = new Foo();
foo.existingProperty = 42; // we obviously can still access original properties
foo.myProperty = ""; // the added property works fine too, no compilation error You'll have to add your {
"files": [
"typings/Foo.d.ts"
]
} |
@neuoy solution kind of worked, but for me it broke other things 😓 Like building with rollup plugin typescript |
Includes augmenting `LinkUI` by new `LinkActionsView` and `LinkFormView` supporting our (again augmented) properties `contentUriPath` and `contentName`. Due to several issues regarding not providing `LinkFormView` and `LinkActionsView` as named exports (which blocks augmenting them due to an unresolved TypeScript Issue), and `SingleBindChain.to` having too strict typing - at least from the implementation point of view here, this resulted in a bunch of changes to get typings straight. See-also: microsoft/TypeScript#14080 See-also: ckeditor/ckeditor5#13864 See-also: ckeditor/ckeditor5#13965
When will this issue be fixed ? |
TypeScript Version: 2.1.5
Code
Expected behavior:
If the class Foo is exported without default in file Foo.ts, and then import {Foo} from './Foo',
it works correctly as example in doc http://www.typescriptlang.org/docs/handbook/declaration-merging.html
Hope import Foo same as import {Foo} behaviors.
Actual behavior:
ERROR message showed.
The text was updated successfully, but these errors were encountered: