How to import other types into my TypeScript custom declarations file?
If we would like to declare that the global.mountWithContext
function exists and has the indicated type we can add the following to an empty declaration file in our project.
import React from 'react';import enzyme from 'enzyme';declare global { namespace NodeJS { interface Global { mountWithContext<P, S>(node: React.ReactElement<any>): enzyme.ReactWrapper<P, S>; } }}
Details
Here is a break down each of the constructs in the above:
The
declare global
block: The purpose of this construct is to modify, to augment if you will, the global scope, either by introducing new declarations or by modifying existing ones, from within a non global context such as a module. Our declaration file is a module because it contains a top-levelimport
clause that importsReactWrapper
from Enzyme. Such a block is called a "Global Augmentation" and may appear in implementation files as well.The
interface Global
wrapped in thenamespace NodeJS
structuring: In our tests we are accessing themountWithContext
function as a member of the global variable, incidentally namedglobal
, that is provided by the Node environment. This variable is already declared by the type declarations for Node at the same level as other environmental globals such asprocess
. However, we need to augment its type, by adding a new member. The type of this globalglobal
is theinterface
Global
already declared inside thenamespace
NodeJS
, by the official declarations for Node. We accomplish this by declaring a new member of theinterface
Global
. Our augmentation needs to be wrapped in thenamespace
containingGlobal
or else it would be considered a separateinterface
. Roughly speaking, lexical scoping applies. (recall that TypeScript interfaces can be declared multiple times in the same scope and that these declarations will be merged)
Notes
Where do we place this declaration?Anywhere that will cause TypeScript to pick it up and include it in our compilation context.By convention we will place it in a file named globals.d.ts in the root directory of our project. (Technically it can be named something else and go in a lower directory).
It is important to note that this declaration file is part of our application code and should be checked into source control.It must not be placed alongside third party declarations in directories such as typings, node_modules/@types, or jspm_packages/npm/@types.
It is also important to note that this augmentation affects TypeScript files (.ts
, .tsx
, .d.ts
) only. If we were rather declaring this function to be picked up by the TypeScript language service simply to provide intellisense when working in .js
or .jsx,
files, this approach will not work.
The function signature is wrong, you have to declare the generic types first, for example:
function foo(T: bar): T // wrongfunction foo<T>(T: bar): T // rightfunction foo<T extends K, K>(T: bar): K // right
In your case something like this should work:
declare function mountWithContext<P, S>(node: React.ReactElement<any>): ReactWrapper<P, S>;
If you happened to know what P
and S
are about you can be more specific, using <P extends React.Component, K>
, for example.