10

How can I import a javascript AMD module into a external TypeScript module?

I'm modularizing my client TypeScript program to use AMD modules managed by bower. As part of this process, a Typescript module becomes a javascript AMD module, which I then publish. Now I have a javascript AMD module that I want to include in a TypeScript module, and I don't want to publish the original TypeScript with the javascript AMD.

I cannot figure out how to write my TypeScript code so that it will load a javascript AMD module for which there is no corresponding TypeScript, and it appears that the most recent versions of TypeScript don't support this yet.

If I start with the example from the 0.9.7 TypeScript specification, section 11.2:

File main.ts:

import log = require("./log"); 
log.message("hello"); 

File log.ts:

export function message(s: string) { 
    console.log(s); 
}

I believe I should be able to modify main.ts so that the compiler resolves the "log" reference to the log.js AMD module. Below is the log.js file that was produced by running tsc --module amd main.ts. It is a correct AMD module.

File log.js:

define(["require", "exports"], function(require, exports) {
    function message(s) {
        console.log(s);
    }
    exports.message = message;
});

To simulate having a javascript AMD module, compile the above example, and then delete the log.ts file. If you now try to compile using the same command, it fails with the following errors:

./main.ts(1,1): error TS2071: Unable to resolve external module '"./log"'.  
./main.ts(1,1): error TS2072: Module cannot be aliased to a non-module type.

How can I now modify main.ts so it compiles and resolves against this log.js AMD module? I can write log.d.ts file if I have to, but would like a method that also works without a declaration file.

If I can learn how to do this in the canonical TypeScript Way, then I can continue the complete modularization of my project.

1 Answer 1

2

How can I now modify main.ts so I can load and use this log.js AMD module?

If you only the log.js available you can tell typescript about the type information from log using declare i.e. create a log.d.ts:

declare module 'log'{
    export function message(s:string);
}

And then use it from main.ts as :

/// <reference path='log.d.ts'/>    

import log = require('log'); 
log.message("hello"); 
Sign up to request clarification or add additional context in comments.

3 Comments

This worked as you wrote it. But if I keep the name from the original example, "./log", then it fails to compile. I searched through the language spec and found section 12.1.6, Ambient External Module Declarations, that describes the restriction that the module name be a top-level (non-relative) name. However, I can't find an explanation for why this is so. I can only guess that there is no real need for such naming? Do you you have an explanation for this restriction? Thanks
Js files should either come from npm or from your RequireJS config. Both of these cases the names are not relative
I found the requirement for using a string for the name of an AMD module confusing, but found this article describing the usage: typescript.codeplex.com/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.