如何为TypeScript配置自定义全局接口(.d.ts文件)?

And*_*ris 48 typescript typescript1.8 typescript-typings typescript2.0

在过去的几个小时里,我一直在努力解决这个问题,而我似乎无法在互联网上找到任何可以清楚解释这个,据说是简单概念的东西.

我目前正在研究一个使用Webpack2和TypeScript的ReactJS项目.除了一件事之外,一切都完美无缺 - 我无法找到一种方法将我自己编写的界面移动到单独的文件中,以便它们对整个应用程序可见.

出于原型设计的目的,我最初在使用它们的文件中定义了接口,但最终我开始添加一些在多个类中需要的东西,并且当所有问题都开始时.无论我对我做了什么改变tsconfig.json,无论我把文件放在哪里,我的IDE和Webpack都抱怨无法找到名字(Could not find name 'IMyInterface').

这是我当前的tsconfig.json文件:

{
  "compilerOptions": {
    "baseUrl": "src",
    "outDir": "build/dist",
    "module": "commonjs",
    "target": "es5",
    "lib": [
      "es6",
      "dom"
    ],
    "typeRoots": [
      "./node_modules/@types",
      "./typings"
    ],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": false,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ],
  "types": [
    "typePatches"
  ]
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我tsconfig.json位于项目目录的根目录中,所有源都在./src,我将自定义.d.ts文件放入./typings并包含在其中typeRoots.

我用TypeScript 2.1.6和2.2.0测试它,但都不起作用.

让它全部工作的一种方法是将我的typings目录移动到src然后,import {IMyInterface} from 'typings/blah'但这对我来说不合适,因为它不是我需要使用的东西.我希望这些界面在我的应用程序中"神奇地"可用.

编辑: 这是一个示例app.d.ts文件:

interface IAppStateProps {
}

interface IAppDispatchProps {
}

interface IAppProps extends IAppStateProps, IAppDispatchProps {
}
Run Code Online (Sandbox Code Playgroud)

我需要export它们declare吗?我希望我不必将它们包装在命名空间中?!

dta*_*enc 111

"神奇可用的接口"或全局类型是非常不鼓励的,应该主要留给遗留.此外,您不应该使用环境声明文件(例如d.ts文件)来编写您正在编写的代码.这些都是代替外部非打字稿代码(基本上将打字稿类型填入js代码中,以便您可以更好地将其与javascript集成).

对于您编写的代码,您应该使用纯.ts文件来定义接口和类型.

虽然不鼓励使用全局类型,但问题的答案是.ts在Typescript中有两种类型的文件.这些被称为scriptsmodules.

任何东西script都是全球性的.因此,如果您在脚本中定义接口,它将在整个应用程序中全局可用(只要脚本通过///<reference path="">标记或通过files:[]或者includes:[]默认情况下包含在编译**/*.tstsconfig.json.

另一种文件类型是"模块",其中的任何内容都是模块module专用的.如果从模块导出任何内容,如果其他模块选择导入模块,则其他模块可以使用.

什么使.ts文件成为"脚本"或"模块"?好吧....如果你import/export在文件中的任何地方使用,该文件就变成了"模块".如果没有 import/export语句,那么它就是一个全局脚本.

我的猜测是你无意中使用importexport在你的声明中将它变成了一个模块,它将你所有的接口转换为该模块中的私有.如果您希望它们是全局的,那么您将确保不在文件中使用导入/导出语句.

  • “神奇的可用接口”是为基于 JS 的 DSL 提供基本 IDE 支持的两种方法之一,另一种方法是 **实际上是数百倍甚至数千倍的困难**:为所有 IDE 编写插件。 (4认同)
  • 该死的人。我只是浪费了一整天,不知道自己在做什么。非常感谢。如果尚未找到此答案,则需要转到官方文档。 (3认同)
  • @dtabuenc 你能支持你的全局类型已被弃用的说法吗?看官方文档我无法得到这样的印象。 (3认同)
  • 你是绝对正确的!事实证明,我的问题是(按照您的建议)我正在将类/接口从其他文件导入到声明文件中。一旦我删除了这些导入,只留下了干净的`Foo {}接口声明,一切就起作用了。根据全局变量-我完全明白了为什么要神奇地使用声明是一种不好的做法,并且正在考虑切换到自定义模块(实际上是尝试过的`declare module MyApp {export interface Foo {}}`,可以通过执行import来成功导入它) {{来自MyApp'`的Foo}),但现在魔术对我有效:) (2认同)

Top*_*ter 11

该术语是“全局”接口,而不是“神奇可用接口”。

在某些.d.ts文件中,我扩展了全局Window接口,例如:

export {};

declare global {
    interface Window {
        // Below just informs IDE and/or TS-compiler (it's set in `.js` file).
        myGlobalVariable: any;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用相同的技术,我们可以创建自定义全局接口(而不是扩展现有接口)。

例子

import React from 'react';

declare global {
    interface MyGlobalInterface {
        myComponentField: React.Component;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,由于.d.ts文件不会产生任何输出,因此我们可以导入任何模块(当然只要该模块已安装package.json)。

另外,上面的示例不需要该行export {};,因为它确实有一个import,我的意思是,规则是至少有一个import或一个export(在撰写本文时)。

最后,.d.ts文件的名称和位置并不重要,但我更喜欢将globals.d.ts文件放在项目的根 js/ts 文件旁边,只是为了确保它首先加载。