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

error importing default function from ambient module #7554

Closed
bcherny opened this issue Mar 16, 2016 · 8 comments
Closed

error importing default function from ambient module #7554

bcherny opened this issue Mar 16, 2016 · 8 comments

Comments

@bcherny
Copy link

bcherny commented Mar 16, 2016

lib:

https://www.npmjs.com/package/textarea-caret

typing (in textarea-caret.d.ts):

declare module "textarea-caret" {
  export default function getCaretCoordinates(
    element: HTMLElement,
    position: number,
    options?: {debug?: boolean}
  ): {left: number, top: number}
}

consuming it (in app.ts):

import * as getCaretCoordinates from 'textarea-caret'
getCaretCoordinates(element, 42)

the function call fails to compile, throwing Error TS2349: Cannot invoke an expression whose type lacks a call signature.

changing the import to import getCaretCoordinates from 'textarea-caret' fixes the issue.

per the es6 module syntax, it seems that the original version is the correct one, right?

@bcherny bcherny changed the title cannot export default function from ambient module error exporting default function from ambient module Mar 16, 2016
@bcherny bcherny changed the title error exporting default function from ambient module error importing default function from ambient module Mar 16, 2016
@blakeembrey
Copy link
Contributor

@bcherny That type definition is incorrect according to the source code, it should be export = getCaretCoordinates. Also, import * as <name> imports the exports from the module, not the default. For importing the default, the syntax is import x from '...'.

Once you're using export = syntax, you need to import with the equivalent import statement of import x = require('...').

@bcherny
Copy link
Author

bcherny commented Mar 16, 2016

Also, import * as imports the exports from the module, not the default. For importing the default, the syntax is import x from '...'.

thanks for clarifying - this makes sense!

Once you're using export = syntax, you need to import with the equivalent import statement of import x = require('...').

this syntax is a bit awkward, since it's using the same keywords as es6, but with different meaning.

@bcherny bcherny closed this as completed Mar 16, 2016
@blakeembrey
Copy link
Contributor

Yes, I know 😄 But there's no equivalent for module.exports = in ES6 syntax, so the ES5 export/import can still be used in situations like these. You could, of course, use the raw require APIs in Node, Webpack, etc. but then TypeScript doesn't know to also import type information. So while const x = require('...') would fallback onto your module loader, import x = require('...') works with TypeScript to emit the correct import and import type information.

@bcherny
Copy link
Author

bcherny commented Mar 16, 2016

actually, with the import a from 'b' syntax, i'm having an issue that typescript compiles import a from 'b' to b.default.a. the problem is, b doesn't have a property called default (a is assigned to b directly).

it's a 3rd party module - what do you suggest?

@blakeembrey
Copy link
Contributor

Use import x = require('...'), it's the issue I mentioned above. import x from '...' is for importing the ES6 default, but for module.exports parity you should use export = and import =.

@bcherny
Copy link
Author

bcherny commented Mar 17, 2016

the import compiles, but the export fails to compile. i also can't seem to find a relevant example anywhere.

new import:

import getCaretCoordinates = require('textarea-caret')

new export:

declare module 'textarea-caret' {
  export = function getCaretCoordinates( // syntax appears to be wrong
    element: HTMLElement,
    position: number,
    options?: {debug?: boolean}
  ): {left: number, top: number}
}

@PAStheLoD
Copy link

I know this is an old issue, and probably solved, but if maybe the following is helpful to others.

declare module 'textarea-caret' {
    function getCaretCoordinates(...): { left: number, top: number }

    export = getCaretCoordinates;
}

@mrdulin
Copy link

mrdulin commented Jul 14, 2017

@blakeembrey @PAStheLoD Thanks. I have this issue too. It works.

Is there some documents about How to write a typescript definition file? You know, for all situations. I read the typescript official documents about the definition files part. But I think the doc is not easy to understand.
Because there is no examples to explain it and lacks of context.

I know what's cmd, amd, umd and global script

But I am confused about when to use export = , export as namespace xxx, declare namespace xxx. And, sometimes, there is no declare keyword. Just some signatures of function and interface.

If there is a repo which has every situation definition file demos, it will be nice. I will star it.

@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
None yet
Projects
None yet
Development

No branches or pull requests

4 participants