I'm trying to wrap my head around the concept of TypeScript .d.ts files and how they function. I'm struggling to comprehend the distinctions between:
- The compiler
- Intellisense (in VS2015 with ReSharper)
- Runtime / the module loader (Systemjs)
I am currently working with the oidc-client-js library, which provides an oidc-client.d.ts file structured like this:
declare var UserManager: Oidc.UserManager;
... more information
declare module "oidc-client" {
export = Oidc;
}
declare namespace Oidc {
interface OidcClient {
... more details
}
interface OidcManager extends OidcClient {
... more details
}
... more information
}
My goal is to utilize the UserManager class in my own TypeScript class, so I do the following:
/// <reference path="../node_modules/oidc-client/oidc-client.d.ts"/>
export class SecurityService {
private manager: Oidc.UserManager;
constructor() {
this.manager = new Oidc.UserManager({
... settings here
});
}
}
However, when I implement this, the following issues arise:
- The compiler notifies me that there is no Oidc namespace for the
new Oidc.UserManager()
call - Intellisense also flags a missing Oidc symbol
- The code does not compile or run due to these errors
To address the compiler's concerns, I modify the code as follows:
/// <reference path="../node_modules/oidc-client/oidc-client.d.ts"/>
export class SecurityService {
private manager: Oidc.UserManager;
constructor() {
this.manager = new UserManager({
... settings here
});
}
}
This adjustment results in:
- The compiler error disappearing
- Intellisense operating smoothly
- An error at runtime stating that UserManager does not exist, since all classes in the oidc-client-js library are under the Oidc namespace requiring
new Oidc.UserManager()
Another solution involves inserting declare var Oidc
into the code:
/// <reference path="../node_modules/oidc-client/oidc-client.d.ts"/>
declare var Oidc;
export class SecurityService {
private manager: Oidc.UserManager;
constructor() {
this.manager = new Oidc.UserManager({
... settings here
});
}
}
With this method:
- The compiler is content
- Intellisense treats everything under Oidc as type
any
- The application functions correctly at runtime
The most effective solution I've discovered involves altering the .d.ts file to use classes instead of interfaces:
declare var UserManager: Oidc.UserManager;
... more info
declare module "oidc-client" {
export = Oidc;
}
declare namespace Oidc {
class OidcClient {
... more data
}
class OidcManager extends OidcClient {
... more data
}
... more info
}
However, this modification requires changes to the definition file. Considering that other definition files typically use interfaces rather than classes, I question whether this issue lies with the definitions file or if it stems from my limited understanding of TypeScript functionality.
If you have any insights or assistance, it would be greatly appreciated.