I am working with Typescript and React. While many react ponents already e with predefined typings, some of them don't. Defining the *.d.ts
file and throwing it into the typings
directory is not a big issue. However, in JavaScript, there are many ways to export something in a module, and it's by no means uniform. The result is that the Typescript piler is happy with my typings, but when I use a typescript import
statement for the typing, then I get undefined
at runtime.
Could somebody clarify how to write proper *.d.ts
files for react ponents? In particular, how do you declare the export
statements in the *.d.ts
file if the original untyped JavaScript file...
- ... uses
export class XYZ
? - ... uses
export default class XYZ
? - ... uses
export namespace XYZ
? - ... uses
export default namespace XYZ
? - ... uses
module.exports
?
There are a lot of possibilities here, and some kind of "cooking recipe" would be nice, i.e. "First, always try method X, if X gives you undefined
at runtime, try Y...".
I am working with Typescript and React. While many react ponents already e with predefined typings, some of them don't. Defining the *.d.ts
file and throwing it into the typings
directory is not a big issue. However, in JavaScript, there are many ways to export something in a module, and it's by no means uniform. The result is that the Typescript piler is happy with my typings, but when I use a typescript import
statement for the typing, then I get undefined
at runtime.
Could somebody clarify how to write proper *.d.ts
files for react ponents? In particular, how do you declare the export
statements in the *.d.ts
file if the original untyped JavaScript file...
- ... uses
export class XYZ
? - ... uses
export default class XYZ
? - ... uses
export namespace XYZ
? - ... uses
export default namespace XYZ
? - ... uses
module.exports
?
There are a lot of possibilities here, and some kind of "cooking recipe" would be nice, i.e. "First, always try method X, if X gives you undefined
at runtime, try Y...".
1 Answer
Reset to default 3Typescript does not know about modules that have been imported via JS. As a result you need to declare the module, and then its exported members.
You can declare the members in your globals definition file more or less the way they've been created in their source file. Since we're talking modules only here, we'll skip the ambient contexts and focus on modules.
Module with Named Components
Given file named view/alpha.js
with contents:
export class Alpha {
howdy() {}
}
OR
class Alpha {
howdy() {}
}
module.exports = {
Alpha: Alpha;
}
Declare module in definition file:
declare module 'view/alpha' {
class Alpha {
howdy() : void;
}
}
Module with Default Export
Given file named view/beta.js
with contents:
export default class Beta {
howdy() {}
}
Declare module in definition file:
declare module 'view/beta' {
export = class Beta {
howdy();
}
}
Module with Default and Other Exports
Given file named view/epsilon
with contents:
export default class Epsilon {
howdy() {}
}
export class Zeta {
howdy() {}
}
Declare module:
declare module 'view/epsilon' {
export default class Epsilon {
howdy() : void;
}
class Zeta {
howdy() : void;
}
}
You referred to:
export default namespace XYZ
export namespace XYZ
This is not valid ES6. If you are referring to something like export Delta
where Delta
contains named classes, then you'd declare it as:
declare module 'view/gamma' {
namespace Delta {
class Omega {
howdy() : void;
}
}
}
Otherwise, can you link an example? I tried googling export default namespace
but didn't get any non-Typescript examples.