64

Is there a way to tell TypeScript to use a certain file (or set of files) as a definition for everything compiled?

My only alternative currently is to add something like this in every single TypeScript file (which seems clunky):

/// <reference path="DefinitelyTyped/requirejs/require.d.ts" />
BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
HotStuff68
  • 925
  • 1
  • 10
  • 13

5 Answers5

43

When using TypeScript's internal module system, you can avoid having any <reference> tags at all in the code. I personally do this because I don't want to encode paths (realtive or absolute) within the code as I constantly move stuff around.

One way to do this is by making sure all required declaration files and TypeScript source files are passed to the compiler as arguments during compile time.

Using gulp together with gulp-typescript simplifies this task. You can set noExternalResolve in gulp-typescript to true, and create gulp tasks that take all your .d.ts files along with your sources and pipe it down to the compiler. When you pull in tsd into your stack, you only need to pass the tsd.d.tsfile that contains references to all other definition files installed via tsd.

UPDATE for TypeScript >= v1.5: you can use a tsconfig.json file, and the compiler will get the ordering of the classes right. This removes the need to use gulp-typescript alltogether. You can either chose to have all files explicitly listed in the tsconfig.json file, or completely leave out the files property to include all *.ts/*.tsx files within the directory the tsconfig.json resides (including all subfolders).

A sample tsconfig.jsonmay look like:

{
    "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "lib": [ "es5", "es2015.promise", "dom" ]
    },
    "include": [
        "src/**/*.ts"
    ]
}
Dynalon
  • 6,577
  • 10
  • 54
  • 84
  • 4
    What if: inside the same module you have class A in file A.ts and class B in file B.ts, and A extends B, you still need to tell to tsc that B.ts should be transpiled beofre A.ts, right? – Paolo May 29 '15 at 06:51
  • Thats right, the order of inclusion matters. That is still one nasty thing about typescript's internal modules (now called `namespaces`) – Dynalon Aug 26 '15 at 06:26
  • 1
    You still need the explicit reference path in a case like what Paolo described, unfortunately. – John Weisz Dec 17 '15 at 23:27
  • @JohnWhite No you don't, you can omit the `files` property in the `tsconfig.json` file; the `tsc` compiler will then include all .ts files in the directory. I've updated the answer to include this information. – Dynalon Dec 18 '15 at 08:00
  • @Dyna Yes, of course, what I actually meant is that you need to manually specify some kind of ordering either way. – John Weisz Dec 18 '15 at 11:08
  • Using gulp, can is it still possible for the compiler to resolve the internal dependencies and order the files in the correct order? I'm trying to get this to work, but no success so far. – Alex Feb 15 '16 at 13:56
  • 1
    Even with using pure visual studio, it refuses to order the files correctly in the concatenated output file. Seems like @JohnWhite is still right? – Alex Feb 15 '16 at 16:55
  • @Alex pure visual studio (without gulp) also just invokes the `tsc` command under the hood - so it suffers the same shortcommings (no ordering of source files). – Dynalon Feb 15 '16 at 18:00
  • 1
    I see now that I misunderstood your answer. I interpreted it like the compiler can get the order right by itself, while what's implicit in your answer is that you have to sort the input to the compiler. – Alex Feb 16 '16 at 08:30
17

What I've learned so far is that /// < reference >-ing a module with reference comments is not a good method.

For example: in case you have a file Foo and a file Bar. Both files use jquery, but only file Foo has a reference comment to jquery. If file Foo is deleted for some reason, your file Bar is broken, because the reference is missing.

If you are using TypeScript >= 2.0 It is better to define the TypeScript definition files (.d.ts) in your tsconfig.json under the "files" section.

This could look like this:

{
  "compileOnSave": true,
  "compilerOptions": {
    "noImplicitAny": true,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5", 
    "outDir": "./Scripts/"
  },
  "files": [
    "./src/foo.ts",
    "./src/bar.ts",
    "./Scripts/typings/jquery/jquery.d.ts",
    "./Scripts/typings/jqueryui/jqueryui.d.ts",
    "./Scripts/MicrosoftMaps/Microsoft.Maps.d.ts"
  ]
}

Using the /// directive (reference comments) is often used in examples to get you started quickly, but it is not a best practice. Also many examples come from a version < TypeScript 2.0.

juFo
  • 17,849
  • 10
  • 105
  • 142
3

Some IDEs auto-detect all the files in a project (Visual Studio).

For everything else, you can create a _references.ts file and put all of your reference comments in there - then you only ever need to add:

/// <reference path="_references.ts" />

...to each file (instead of possibly many).

Your IDE may also support tsconfig files.

Community
  • 1
  • 1
Fenton
  • 241,084
  • 71
  • 387
  • 401
3

This question is a duplicate of Reference typescript definitions in one file, instead of all JS files?

The answer is, for now, add each file you want to reference to your tsconfig.json file's "files" section. It's still many lines, but all in one file.

In future when Typescript 2 is released you can then use the "filesGlob" section and solve the problem in two lines.

Community
  • 1
  • 1
Richard
  • 14,798
  • 21
  • 70
  • 103
  • 1
    Better option is to not specify "files" at all. https://github.com/Microsoft/TypeScript/wiki/tsconfig.json#details `If no "files" property is present in a tsconfig.json, the compiler defaults to including all TypeScript (*.ts or *.tsx) files in the containing directory and subdirectories. When a "files" property is present, only the specified files are included.` – sbedulin Jan 18 '16 at 09:28
  • 2
    This is not necessarily "better". In a real-world project, your exclude list would grow enormously (i.e. I regularly have to exclude `node_modules`, `dist`, `bower_components`, `typings` etc.). I am desperately waiting for `filesGlob` to land in core TS. – Dynalon Feb 15 '16 at 17:59
0

I've started recently with TypeScript and as I've understood the internal modules resolution is that yes, you can compile all .ts files from the tsconfig.json's directory and all its subdirectories, provided that you don't have set .ts files in it without /// <references path="" />.

But the order in which the .ts files are compiled into resulting .js files is not determined by the dependencies the files (or classes they contain) have. So it is possible to have a situation where the child class is compiled before the parent one (child inherits from parent relation). Then the code won't run, even though it is compiled successfully. It will complain that it couldn't understand the parent class within the child class. Therefore you need to add a /// <references path="" /> as a hint to the compiler to resolve the dependencies between .ts files.

This is want the Typescript documentation says:

The /// directive is the most common of this group. It serves as a declaration of dependency between files.

Triple-slash references instruct the compiler to include additional files in the compilation process.

They also serve as a method to order the output when using --out or --outFile. Files are emitted to the output file location in the same order as the input after preprocessing pass.

rphv
  • 5,409
  • 3
  • 29
  • 47