Skip to content
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

declaration: Namespace which exports class can't be merged with variable #13536

Closed
ikokostya opened this issue Jan 17, 2017 · 7 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@ikokostya
Copy link
Contributor

ikokostya commented Jan 17, 2017

TypeScript Version: 2.2.0-dev.20170117

I try to write declaration for got module.

Code

// Use interface, because `got` function has `delete` property.
interface GotApi {
    (): any;
    delete(): any;
}

declare var got: GotApi;

declare namespace got {
    export class HTTPError extends Error {}
}

export = got;

Expected behavior:

No errors. HttpError class is available using got exported variable:

import * as got from 'got';

// let error = ...
if (error instanceof got.HTTPError) {
}

Actual behavior:

I get compiler errors for declaration file:

index.d.ts(6,13): error TS2300: Duplicate identifier 'got'.
index.d.ts(8,19): error TS2300: Duplicate identifier 'got'.

Used tsconfig.json:

{
    "compilerOptions": {
        "module": "commonjs",
        "moduleResolution": "node",
        "target": "es2015",
        "noImplicitAny": true,
        "strictNullChecks": true,
        "outDir": "build"
    }
}

Related issue: #1784

@aluanhaddad
Copy link
Contributor

Note that the GotApi interface is not exported

@ikokostya
Copy link
Contributor Author

Note that the GotApi interface is not exported

How interface should be exported? This code (similar to request declaration) also isn't compiled with the same error:

declare namespace got {
    export interface GotApi {
        (): any;
        delete(): any;
    }

    export class HTTPError {}
}

declare var got: got.GotApi;
export = got;

If remove class export from namespace, compilation is completed:

interface GotApi {
    (): any;
    delete(): any;
}

declare var got: GotApi;

declare namespace got {
    // export class HTTPError extends Error {} <--- Comment this line
}

export = got;

@mhegazy
Copy link
Contributor

mhegazy commented Jan 17, 2017

Ideally this would be rewitten as function+namespace but it can not, #1784 (and #9846) track that.

Instantiated namespaces (i.e. ones that has a value in them) can not merge with variables, since one of them will override the other at run-time.

you can write your declaration as such:

declare class HTTPError { }

interface GotApi {
    (): any;
    delete(): any;
    HTTPError: typeof HTTPError;
}

declare var got: GotApi;
export = got;

@mhegazy mhegazy added the Duplicate An existing issue was already created label Jan 17, 2017
@ikokostya
Copy link
Contributor Author

ikokostya commented Jan 17, 2017

Instantiated namespaces (i.e. ones that has a value in them) can not merge with variables, since one of them will override the other at run-time.

As I understand from documentation about declaration merging function and variable are value creating declarations, i.e. code

interface GotApi {
    (): any;
}
declare var got: GotApi;
declare namespace got {
    export class HTTPError {}
}
export = got;

and

declare var got: () => any;
declare namespace got {
    export class HTTPError {}
}
export = got;

fails to compile. But function declaration is compiled:

declare function got(): any;
declare namespace got {
    export class HTTPError {}
}
export = got;

Why this happen?

Also, I propose to make error message is more detailed, because current message error TS2300: Duplicate identifier 'got'. is cryptic at first glance. For example, namespace and variable declaration can't be merged.

@mhegazy
Copy link
Contributor

mhegazy commented Jan 17, 2017

var got: ()=> any is treated as a variable, and not as a function declaration. the reason is a variable can be assigned to later on where as a function can not.

@ikokostya
Copy link
Contributor Author

@mhegazy Thanks for explanation.

@BendingBender
Copy link

@mhegazy So why is it then not allowed to merge a declare const with a declare namespace? AFAIK, const is also not assignable more than once.

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants