-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Importing Typescript class from another npm library #2262
Comments
The .js is the executable, and the .d.ts is the type information that goes with it. in C terms, .js is your .dll , the .d.ts is your matching .h file. on the consumption side, your user would do
To load the types you need an explicit reference to the .d.ts, this is a bug that should be fixed in future releases (issue #247), to do that in your consumer add: /// <reference path="node_module/module/module.d.ts" />
import m = require("module"); |
I tried to write like you suggested: class Person {
name:string;
toString():string{
return "the person name is "+name;
}
} than to use it, I tried to compile it using the command /// <reference path="node_modules/demo/person.d.ts" />
import Person = require('person');
var p:Person;
console.log(p.toString()); my node_modules\demo\person.d.ts looks like this declare class Person {
public name: string;
public toString(): string;
} but when I compile using this command:
What am I missing? |
You need to export the class: class Person {
name:string;
toString():string{
return "the person name is "+name;
}
}
export = Person; A file with no imports or exports is not considered a module (but rather it is considered a "global" file that will be included using <script/> tag or some other means). |
I tried that but I still have problems with line:2
I didn't find any reference which explains it clearly. |
Here is what i have. file: demo/person.ts class Person {
name:string;
toString():string{
return "the person name is " + this.name;
}
}
export = Person; file: test.ts /// <reference path="demo/person.d.ts" />
import person = require("./demo/person")
console.log(new person().toString()); call the compiler on test.ts:
run it:
this the result I am getting:
|
Ok. It works. Thanks a lot! Let me ask you another question. demo\person.ts module demo{
class Person {
name:string;
toString():string{
return "the person name is " + this.name;
}
}
export = Person;
} so when I'll import the file I'll get the module, and I'll aggregate several classes under one module: /// <reference path="demo/person.d.ts" />
import demo = require("./demo/person")
console.log(new demo.person().toString()); how to do it exactly? |
It sounds like you want to export Person rather than export=. Export= will make the module behave like the target identifier. So in this case you could say |
your module demo is an "internal" module. so that is not going to work with node. This is a tricky issue that ppl have commonly ran into. i would look at the module wiki page first. |
This is a crazy amount of work involved that typescript offers no help with to get a basic unit of code sharing/reuse. |
If you have some specific suggestions please do file issues. Modules in JS have been difficult for some time now and they're unfortunately complicated in TS as well. That should be getting better with ES6 modules. In an ideal world you might expect things like an npm JS package to include a .d.ts (we've had suggestions of this sort) and less confusion over what is/isn't an internal/external module and what that really means (we have a suggestion to use namespace instead of internal module to help reduce confusion). |
@danquirk - Definitely, I've just opened another ticket with some thoughts. And I think I've probably got another volley of observations as I try to articulate just what makes all of this so difficult. |
There does not seem to be much tooling (external to the ts compiler) available either. A similar question I asked n StackOverflow is not attracting many answers... (http://stackoverflow.com/questions/31654376/automatically-generating-ambient-module-declarations) This issue should trigger more attention. The ability to easily write reusable (external) modules - usable both from typescript and javascript - is key to large application and APIs development and maintenance. |
@bgrieder i am working on this right now. can you elaborate on your scenario.. For input: `api/Token.ts`` interface Token {
code: string
}
export {Token}
export * from './api/Token' would
declare module "api/Token" {
interface Token {
code: string
}
export {Token}
}
declare module "index" {
export * from "api/Token";
} (2) knowing that the entry module is "index.ts", follow the exported surface area of that and just emit its shape as such: // came from api\token.ts, then exported through `export *`
export interface Token {
code: string
} (3) bundle that and rename it maybe.. would you want it to bundle, like: declare module "myPackage" {
export interface Token {
code: string
}
} |
also as a note, your post on stackoverflow assumes that a default export can be exported. that is not true based on the ES6 spec. so interface Token {
}
export default Token; // this is the default export, can only be imported using import d from "api\Token";
export * from `.\api\token`; // token exports only a default export, * will bring you nothing. so if you want to export token, you will either have to 1. mark interface export interface Token { // add an export specifier. this way it is exported as part of the module and as a default
}
export default Token; or
import Token from ".\api\token";
export {Token}; |
I'd like to chime in with my currently (as of 1.5) unsupported scenario: I have a typescript library I'd like to publish to NPM, let's call it "CoreLib". And a program I'd like to reference this library. lets call it "MyApp"
The
I'm using CommonJs, and the above is written using the 1.4 module syntax, (in case there is something in 1.5 that makes this slicker, I haven't looked into that) So I'd like to publish unfortunatly, the following code does not work:
I hope this makes sense. Please let me know if you need clarification. |
currently my workaround is that both
|
@jasonswearingen i think the change in #2338, @basarat has already submitted a PR (#3147) for the change, and @vladima is doing the infrastructure/tooling work needed and should be done soon. |
@mhegazy Glad to hear you are working on it ! On the fact that default exports cannot be re-exported: I missed that entirely from the specs. The goal would be for import Token from ".\api\token";
import User from ".\api\User";
export {Token, User}; My preferred end-result would be your scenario 3) i.e. declare module "myPackage" {
export interface Token {
code: string
}
export interface User {
username: string
}
} The reasons are that this is consistent with the content of |
I guess the single |
@mhegazy awesome, thanks for the links and status update. |
I've come up with one solution that already seems to work today. It relies on a small tool called autodts which is based on previous work from Typings are packaged to two There's a blog post with more detailed information. |
Since work is performed on this issue, shouldn't this issue be re-opened or its content moved to a new issue ? |
@bgrieder the work referenced in #2338 has been completed and is in master as well as in TS 1.6-beta release. See PRs: #3147, #4154, and #4352. With TS1.6, you do can import node typing just like you import the js files, which eliminates the need to bundle your .d.ts into a single file. can you give it a try and let us know if the issue has been truly resolved or not. |
@mhegazy The answer is Yes (99%) ! Details posted in this issue: #247 EDIT |
@mhegazy is there any example project setup demonstrating how to use an external typescript module ? Optimally a project with a proper test setup to be more realistic (btw i mean a TS module referencing another TS module, both of which using some node standard modules like streams). I am basically stuck with using require to import my own modules since all generated d.ts files include reference statements to e.g node.d.ts which i use in the referencing module too. Causing a duplicate identifier error. Example:
Both modules are referencing node.d.ts and others of course in the ts files. PS: the tsconfig.json in both projects excludes the typings folders its really just the /// reference statements, removing them and using standard require then works without errors but leaves me without types of course. |
@matthiasg this is the problem that #7156 attempts to solve. node.d.ts should be included only once though it is referenced by both modules. For now the recommendation is to not add /// to your dependencies, as that force your user to include them. see https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Typings%20for%20NPM%20Packages.md that means that your sources should not include the #7156 is scheduled for the next release, TS 2.0 and is available in master already, so if you want to try it, you can use |
Good to hear that work is being done there. PS: If i do not add the /// statements though VSCode and Sublime dont work correctly and do not offer intellisense. |
Hi,
I'm working on node.js with npm. I've written a TS library and I want to use it in another project by doing npm install.
I'm not sure what will should be the contents in my npm package:
should it be only .js, only .ts, or .js with additional declaration files (d.ts)?
Furthermore if I'm using the third option, what exactly am I writing in the definition file? how exactly am I using it?I'm not sure what's the connection between d.ts and the actual javascript.
I see a lot of different answers but most them didn't help me.
Thanks,
Omer
The text was updated successfully, but these errors were encountered: