The solutions provided above can all coexist harmoniously and complement each other effectively. The key lies in the understanding that declaration files (non-modules) need to be somehow accessible to the project, as they do not have exports. Additionally, there exists a syntax that enables any module file (any file utilizing imports/exports, essentially anything within your src folder) to add ambient declarations.
Understanding Ambient Declarations (Non-Modules)
- These files must be included in the project (e.g., through
tsconfig.json
under "include"
)
- They should not include any
import
or export
statements
- To import external types, a specific syntax is available
tsconfig.json
{
"include": ["./src/global.d.ts"],
// or use wildcard
"include": ["**/*.d.ts"],
}
src/globals.d.ts
// Global types
type AnyObject<T = any> = Record<string, T>
type AnyFunction = (...args: any[]) => any
// Enhancing existing interfaces via interface merging
interface Window {
console: AnyObject
}
// Importing external types
declare type BaseContract = import('ethers').BaseContract
declare type _MockContract = import('ethereum-waffle').MockContract
declare type Stub = import('ethereum-waffle').Stub
// Re-defining an existing interface to provide improved typings.
interface MockContract<T extends BaseContract = BaseContract> extends _MockContract {
mock: {
[key in keyof T['functions']]: Stub
}
}
Javascript Modules
- Modules consist of files with
import
or export
statements,
essentially every file within your src
folder.
- Any js (module) file can contribute ambient declarations.
src/app.ts
import React from 'react'
export default MyApp(props: AppProps) {
return <div>Hi</div>
}
// Ambient declarations
declare global {
interface Window {
console: AnyObject
}
}
To prevent confusion among colleagues, place this disclaimer at the beginning of your Ambient Declarations file
////// -----------------------------------------------------------------------------------------------------------------
/*//// -----------------------------------------------------------------------------------------------------------------
This file serves as an “Ambient declarations file”. The defined types here are globally accessible.
For more information, refer to https://stackoverflow.com/a/73389225/985454
Avoid using `import` and `export` directly in this file! It disrupts ambience.
To import external types in an ambient declarations file (this file), follow this format:
*//**
* @example
* declare type React = import('react')
*//*
To incorporate ambient declarations from any file, including non-ambient ones, use this approach:
*//**
* @example
* declare global {
* interface Window {
* ethereum: any
* }
* }
*//*
/*//// -----------------------------------------------------------------------------------------------------------------
////// -----------------------------------------------------------------------------------------------------------------
// Your type definitions go here ...