I did manage it this time... Sort of. Unfortunately there was a problem which I discovered right at the end. An issue with the TypeScript / Visual Studio tooling. So, just to be clear, this is not a blog post of "do this and it will work perfectly". On this occasion there will be some rough edges. This post exists, as much as anything else, as a record of the problems I experienced - I hope it will prove useful. Here we go:
I'm going to use one of the test files in my my side project Proverb. It's the tests for an AngularJS controller called
Righteo. Let's flip the switch.
sageDetail.js you shall go to the ball! One wave of my magic wand and
sageDetail.ts... Alakazam!! Of course we've got to do the fiddling with the
And add this:
What next? I've a million red squigglies in my code. It's "could not find symbol" city. Why? Typings! We need typings! So let's begin - I'm needing the Jasmine typings for starters. So let's hit NuGet and it looks like we need this:
And I'll also take this
Bingo bango - a difference. I no longer have red squigglies under the Jasmine statements (
it etc). But alas, I do everywhere else. One in particular draws my eye...
That's right it's an implicit global. Quickly fixed:
We need more types. We're going to need the types created by our application; our controllers / services / directives etc. As well that we need the types used in the creation of the app. So the Angular typings etc. Since we're going to need to use
reference statements to pull in the types created by our application I might as well use them to pull in the required definition files as well (eg
Now we need to work our way through the "variable 'x' implicitly has an 'any' type" messages. One thing we need to do is to amend our original sageDetails.ts file so that the
sageDetailRouteParams interface and
SageDetail class are exported from the controllers module. We can't use the types otherwise. Now we can add typings to our file - once finished it looks like this:
Except it's not. When I run the tests using Chutzpah my
sageDetail controller tests aren't found. My spider sense is tingling. This is something to do with the
reference statements. They're throwing Chutzpah off. No bother, I can fix that with a quick tweak of the project file:
The TypeScript compiler will now strip comments; which includes the
reference statements. Now my tests are detected *and* they run. Yay!
Yup it's dead. Whilst the compilation itself has no issues, take a look at the errors being presented for just one of the files back in the original web project:
It looks like having one TypeScript project in a solution which uses
reference comments somehow breaks the implicit referencing behaviour built into Visual Studio for other TypeScript projects in the solution. I can say this with some confidence as if I pull out the
reference comments from the top of the test file that we've converted then it's business as usual - the TypeScript Language Service lives once more. I'm sure you can see the problem here though: the TypeScript test file doesn't compile. All rather unsatisfactory.
I suspect that if I added
reference comments throughout the web project the TypeScript Language Service would be just fine. But I rather like the implicit referencing functionality so I'm not inclined to do that. After reaching something of a brick wall and thinking I had encountered a bug in the TypeScript Language service I raised an issue on GitHub.
Thanks to the help of Mohamed Hegazy it emerged that the problem was down to missing
reference comments in my
sageDetail controller tests. One thing I had not considered was the 2 different ways each of my TypeScript projects were working:
- Proverb.Web uses the Visual Studio implicit referencing functionality. This means that I do not need to use
referencecomments in the TypeScript files in Proverb.Web.
referencecomments to resolve references.
reference comments to pull in Proverb.Web TypeScript files. Those files have dependencies which are *not* stated using
reference comments. So the compiler trips up when it tries to walk the dependency tree - there are no
reference comments to be followed! So for example,
common.ts has a dependency upon
logger.ts. Fixing the TypeScript Language Service involves ensuring that the full dependency list is included in the
sageDetail controller tests file, like so:
With this in place you have a working solution, albeit one that is a little flaky. An alternative solution was suggested by Noel Abrahams which I quote here:
Why not do the following?
- Compile Proverb.Web with --declarations and the option for combining output into a single file. This should create a Proverb.Web.d.ts in your output directory.
I don't think directly referencing TypeScript source files is a good idea, because it causes the file to be rebuilt every time the dependant project is compiled.
Mohamed rather liked this solution. It looks like some more work is due to be done on the TypeScript tooling to make this less headache-y in future.