打字稿中的全局类型

Tal*_*Tal 16 typescript typescript-typings

有没有办法在您的打样文件中创建一个定义全局可访问类型的文件?

我喜欢打字稿但发现当我想要真正的类型安全时,我必须明确地从整个系统中导入类型.这很烦人.

Rai*_*aid 18

有点晚了,但是,正如我所注意到的,您可以在项目中的任何位置添加 file.d.ts ,并且它将被拾取。

例如,在我的项目中我想要一个:

Optional<T> = T | null;
Run Code Online (Sandbox Code Playgroud)

而且我不知道在哪里添加它,所以我在一个文件夹中添加了一个common.d.ts,并添加:

declare type Optional<T> = T | null;
Run Code Online (Sandbox Code Playgroud)

现在它已被拾取并且没有错误。甚至不需要导入它。这当然正在 vscode 中进行测试,不确定它是否适用于您的编辑器。

(当然取决于您的文件包含/排除规则,但大多数项目都包含所有 *.ts)

  • 对于从 FlowJS 迁移非常有帮助 (2认同)

Eli*_*ias 17

我发现接受的答案不起作用(也许这是一些需要完成的配置?)。因此,经过一些修补,我让它为我工作(也许我也有一些奇怪的配置选项?如果它不起作用,请告诉我,我将删除此答案)。

  1. 在合适的文件夹中创建定义文件。我将使用types/global.d.ts
  2. 检查您的tsconfig.json并包含"*": ["types/*.d.ts"]paths. (如果您愿意,您也应该能够直接寻址创建的文件)。
  3. 将您的全局定义直接放入文件NO declare global或类似文件的根目录中。

现在你应该可以使用在这个文件中声明的类型(用 typescript 3.9.6 和 3.7.5 测试)。

示例文件:

// global.d.ts
declare interface Foo {
    bar: string;
    fooBar: string;
}
Run Code Online (Sandbox Code Playgroud)

tsconfig应该是什么样子:

// global.d.ts
declare interface Foo {
    bar: string;
    fooBar: string;
}
Run Code Online (Sandbox Code Playgroud)

  • 如果有人愿意解释“声明全局”那就太酷了。正如官方文档中所述。 (2认同)
  • 这个解决方案对我有用。“接受”的答案没有。感谢您! (2认同)
  • 这对我也有用。接受的答案没有。 (2认同)
  • 如果您在添加上述解决方案后遇到 eslint 问题,您可以在顶部添加带有全局和名称的注释 - 更多详细信息:https://eslint.org/docs/rules/no-undef (2认同)

Qwe*_*rty 17

上述所有答案实际上可以共存并协同工作。关键是要理解声明文件(非模块)必须可以“以某种方式”被项目发现,因为它们不包含导出。并且有一种语法允许任何模块文件(任何使用导入/导出的文件,基本上是 src 文件夹中的任何文件)也贡献环境声明。

环境声明文件(非模块)

  • 必须包含在项目中(即tsconfig.json "include"
  • 不得包含任何importorexport语句
  • 要导入外部类型,有一个特殊的语法
tsconfig.json
{
  "include": ["./src/global.d.ts"],
  // or wildcard
  "include": ["**/*.d.ts"],
}
Run Code Online (Sandbox Code Playgroud)
src/globals.d.ts
// Global types

type AnyObject<T = any> = Record<string, T>
type AnyFunction = (...args: any[]) => any

// Contributing to existing interfaces (interface merging)

interface Window {
  console: AnyObject
}

// Importing

declare type BaseContract = import('ethers').BaseContract
declare type _MockContract = import('ethereum-waffle').MockContract
declare type Stub = import('ethereum-waffle').Stub
// Here we are re-defining an existing interface to provide better typings.
interface MockContract<T extends BaseContract = BaseContract> extends _MockContract {
  mock: {
    [key in keyof T['functions']]: Stub
  }
}
Run Code Online (Sandbox Code Playgroud)

JS 模块

  • import模块是包含或语句的文件export
    因此基本上是src文件夹中的每个文件。
  • 任何 js(模块)文件都可以提供环境声明。
src/app.ts
import React from 'react'

export default MyApp(props: AppProps) {
  return <div>Hi</div>
}

// Ambient declarations

declare global {
  interface Window {
    console: AnyObject
  }
}
Run Code Online (Sandbox Code Playgroud)

将其放在环境声明文件的顶部,以避免同事混淆

////// -----------------------------------------------------------------------------------------------------------------
/*//// -----------------------------------------------------------------------------------------------------------------

This file is an "Ambient declarations file". The types defined here are available globally.
More info here: /sf/answers/5137245781/

Don't use `import` and `export` in this file directly! It breaks ambience.
To import external types in an ambient declarations file (this file) use the following:

*//**
* @example
* declare type React = import('react')
*//*

To contribute ambient declarations from any file, even non-ambient ones, use this:

*//**
* @example
* declare global {
*   interface Window {
*     ethereum: any
*   }
* }
*//*

/*//// -----------------------------------------------------------------------------------------------------------------
////// -----------------------------------------------------------------------------------------------------------------

// Your type definitions here ...
Run Code Online (Sandbox Code Playgroud)


byy*_*ung 15

除了塞巴斯蒂安·塞巴尔德的回答之外

别忘了

export {} 
Run Code Online (Sandbox Code Playgroud)

这使得它成为实际的模块。

像这样。

这是有效的。

declare global {
    /*~ Here, declare things that go in the global namespace, or augment
     *~ existing declarations in the global namespace
     */
    interface String {
        fancyFormat(opts: StringFormatOptions): string;
    }
}
export {}
Run Code Online (Sandbox Code Playgroud)


Seb*_*ald 13

是的,这是可能的.您可以在此处找到所有信息:https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html

重要的是这个:

declare global {
    /*~ Here, declare things that go in the global namespace, or augment
     *~ existing declarations in the global namespace
     */
    interface String {
        fancyFormat(opts: StringFormatOptions): string;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我想也许我的问题更多的是了解.d.ts文件的导入方式.因为我甚至无法判断这些文件是否正在导入.除了未知类型之外没有错误消息. (8认同)
  • 谢谢,我尝试了这个并将其放入打字文件中,但无法加载。是否需要使用一个名称,或者我应该将其包含在我的入口点中? (2认同)
  • 尝试此操作时,我收到“ts(2669)”。 (2认同)
  • @wegry 看起来像格式错误:/sf/ask/3999269991/ (2认同)