typescript 中的全局类型

smdnsysy  于 2023-03-04  发布在  TypeScript
关注(0)|答案(5)|浏览(166)

有没有办法在您的typescript文件中创建一个定义全局可访问类型的文件?
我喜欢typescript,但是我发现当我想要真正的类型安全时,我不得不显式地从整个系统导入类型,这相当烦人。

qlckcl4x

qlckcl4x1#

是的,这是可能的。您可以在这里找到所有信息: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;
    }
}
juud5qan

juud5qan2#

我发现接受的答案不起作用(也许是需要做一些配置?)。所以经过一些修补,我让它为我工作(也许我也有一些奇怪的配置选项?让我知道如果它不起作用,我会删除这个答案)。
1.在合适的文件夹中创建定义文件。我将使用types/global.d.ts
1.检查您的tsconfig.json并将"*": ["types/*.d.ts"]包含在paths下(如果您愿意,您还应该能够直接访问创建的文件)。
1.将全局定义直接放入文件NOdeclare global或类似文件的根目录中。
现在,您应该可以使用这个文件中声明的类型了(使用typescript 3.9.6和3.7.5进行了测试)。
示例文件:

// global.d.ts
declare interface Foo {
    bar: string;
    fooBar: string;
}

您的tsconfig应该是什么样子:

[...]
"paths": {
    "*": ["types/*.d.ts"]
},
[...]
i7uq4tfw

i7uq4tfw3#

有点晚了,但是,你可以在你的项目中的任何地方添加一个文件.d.ts,就像我注意到的那样,它会被选中。
例如,在我的项目中,我希望:

Optional<T> = T | null;

我不知道该把它加到哪里,所以我在一个文件夹里加了一个通用的.d.ts,然后加了一句:

declare type Optional<T> = T | null;

现在它被选中了,没有错误。甚至不需要导入它。当然这是在vscode中测试的,不确定它是否能在你的编辑器中工作。
(当然,这取决于您的文件包含/排除规则,但大多数项目都包含所有 *.ts)

qxsslcnc

qxsslcnc4#

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

环境声明文件 (非模块)

  • 必须包含在项目中(即tsconfig.json"include"
  • 不能包含任何importexport语句
  • 要导入外部类型,有一种特殊的语法
tsconfig.json
{
  "include": ["./src/global.d.ts"],
  // or wildcard
  "include": ["**/*.d.ts"],
}
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
  }
}

JS模块

  • 模块是包含importexport语句的文件,

基本上就是src文件夹中的每个文件。

  • 任何js(模块)文件都可以提供环境声明。
一米九一x
import React from 'react'

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

// Ambient declarations

declare global {
  interface Window {
    console: AnyObject
  }
}

将其放在Ambient Declarations文件的顶部,以避免同事混淆

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

This file is an "Ambient declarations file". The types defined here are available globally.
More info here: https://stackoverflow.com/a/73389225/985454

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 ...
v09wglhw

v09wglhw5#

除了塞巴斯蒂安·西博尔德的回答
别忘了

export {}

这使其成为实际模块。
就像这样。
这是工作。

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 {}

相关问题