216

我正在使用我自己和第三方的很多库。我看到“typings”目录包含一些用于 Jquery 和 WinRT...但它们是如何创建的?

4

9 回答 9

257

有几个选项可供您使用,具体取决于相关库、编写方式以及您正在寻找的准确度。让我们按照可取性的大致降序来回顾这些选项。

也许它已经存在

始终首先检查 DefinitelyTyped ( https://github.com/DefinitelyTyped/DefinitelyTyped )。这是一个包含数以千计的 .d.ts 文件的社区存储库,很可能您正在使用的东西已经存在。您还应该检查 TypeSearch ( https://microsoft.github.io/TypeSearch/ ),它是 NPM 发布的 .d.ts 文件的搜索引擎;这将比DefiniteTyped 有更多的定义。一些模块也将它们自己的定义作为其 NPM 分发的一部分发布,因此在尝试编写自己的模块之前还要看看是否是这种情况。

也许你不需要一个

TypeScript 现在支持该--allowJs标志,并将在 .js 文件中进行更多基于 JS 的推理。您可以尝试将 .js 文件与--allowJs设置一起包含在编译中,以查看这是否为您提供了足够好的类型信息。TypeScript 将识别这些文件中的 ES5 样式类和 JSDoc 注释等内容,但如果库以奇怪的方式初始化自身,则可能会出错。

开始使用--allowJs

如果--allowJs给了你不错的结果并且你想自己编写一个更好的定义文件,你可以结合--allowJs使用--declaration来查看 TypeScript 对库类型的“最佳猜测”。这将为您提供一个不错的起点,如果 JSDoc 注释写得很好并且编译器能够找到它们,它可能与手写文件一样好。

开始使用 dts-gen

如果--allowJs不起作用,您可能需要使用 dts-gen ( https://github.com/Microsoft/dts-gen ) 作为起点。此工具使用对象的运行时形状来准确枚举所有可用属性。从好的方面来说,这往往非常准确,但该工具尚不支持抓取 JSDoc 注释以填充其他类型。你这样运行:

npm install -g dts-gen
dts-gen -m <your-module>

这将your-module.d.ts在当前文件夹中生成。

点击贪睡按钮

如果你只是想稍后再做,暂时不用类型,现在可以在 TypeScript 2.0 中编写

declare module "foo";

这将让您使用 typeimport的模块。如果你有一个你想稍后处理的全局,只需写"foo"any

declare const foo: any;

这会给你一个foo变量。

于 2012-10-02T17:11:37.150 回答
62

您可以tsc --declaration fileName.ts像 Ryan 所描述的那样使用,或者您可以在假设您已经拥有一个under 您的项目的情况下指定declaration: trueunder 。compilerOptionstsconfig.jsontsconfig.json

于 2016-08-04T00:54:52.223 回答
17

处理这个问题的最好方法(如果声明文件在definitelyTyped上不可用)是只为您使用的东西而不是整个库编写声明。这大大减少了工作量 - 此外,编译器可以通过抱怨缺少方法来提供帮助。

于 2015-10-19T09:08:04.660 回答
16

正如 Ryan 所说,tsc 编译器有一个从文件--declaration生成文件的开关。另请注意(排除错误)TypeScript 应该能够编译 Javascript,因此您可以将现有的 javascript 代码传递给 tsc 编译器。.d.ts.ts

于 2012-10-02T23:02:56.600 回答
14

创建自己的库时,您可以*.d.ts使用 tsc(TypeScript Compiler)命令创建文件,如下所示:(假设您正在将库构建到dist/lib文件夹中)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): 生成*.d.ts文件
  • --declarationDir dist/lib:生成的声明文件的输出目录。
  • --declarationMap:为每个对应的“.d.ts”文件生成一个源映射。
  • --emitDeclarationOnly: 只发出 '.d.ts' 声明文件。(没有编译的 JS)

(有关所有命令行编译器选项,请参阅文档)

或者例如在你的package.json

"scripts": {
    "build:types": "tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly",
}

然后运行:(yarn build:typesnpm run build:types

于 2019-09-23T16:24:12.360 回答
7

http://channel9.msdn.com/posts/Anders-Hejlsberg-Steve-Lucco-and-Luke-Hoban-Inside-TypeScript在 00:33:52 中所述,他们构建了一个工具来将 WebIDL 和 WinRT 元数据转换为TypeScript d.ts

于 2012-10-02T20:24:27.097 回答
3

这是一些 PowerShell,它创建了一个单一的 TypeScript 定义文件,一个包含多个*.js现代 JavaScript 文件的库。

首先,将所有扩展名更改为.ts.

Get-ChildItem | foreach { Rename-Item $_ $_.Name.Replace(".js", ".ts") }

其次,使用 TypeScript 编译器生成定义文件。会有一堆编译器错误,但我们可以忽略它们。

Get-ChildItem | foreach { tsc $_.Name  }

最后,将所有*.d.ts文件合并为一个index.d.ts,删除import语句并default从每个导出语句中删除。

Remove-Item index.d.ts; 

Get-ChildItem -Path *.d.ts -Exclude "Index.d.ts" | `
  foreach { Get-Content $_ } | `
  where { !$_.ToString().StartsWith("import") } | `
  foreach { $_.Replace("export default", "export") } | `
  foreach { Add-Content index.d.ts $_ }

index.d.ts这以包含许多定义的单个可用文件结束。

于 2016-08-19T22:44:31.403 回答
2

我会寻找支持 Script# 或 SharpKit 的 3rd 方 JS 库的现有映射。这些 C# 到 .js 交叉编译器的用户将面临您现在面临的问题,并且可能已经发布了一个开源程序来扫描您的 3rd 方库并转换为骨架 C# 类。如果是这样,请破解扫描程序以生成 TypeScript 代替 C#。

如果做不到这一点,将 3rd 方库的 C# 公共接口转换为 TypeScript 定义可能比通过阅读源 JavaScript 来做同样的事情更简单。

我特别感兴趣的是 Sencha 的 ExtJS RIA 框架,我知道已经发布了一些项目来为 Script# 或 SharpKit 生成 C# 解释

于 2012-10-04T17:37:44.883 回答
1

此答案显示了如何使用 typescript 编译器 API 在独立函数中执行此操作:

import ts from 'typescript';
function createDTsTextsFromJsFilePaths(
  jsFileNames: string[]
): Record<string, string> {
  const options = {
    allowJs: true,
    declaration: true,
    emitDeclarationOnly: true,
  };
  // Create a Program with an in-memory emit
  const createdFiles: Record<string, string> = {};
  const host = ts.createCompilerHost(options);
  host.writeFile = (fileName: string, contents: string): void => {
    const dtsName = fileName.replace('.js', '.d.ts');
    createdFiles[dtsName] = contents;
  };
  // Prepare and emit the d.ts files
  const program = ts.createProgram(jsFileNames, options, host);
  program.emit();
  return createdFiles;
}
////////////// test code below here ///////////////////////////////////
import fs from 'fs'
const jsTest = 
`
"use strict"
function x(){
  return {
    a: 1, 
    b: ()=>'hello'
  }
}
`;
const jsPath = '/tmp/jstest.js';
fs.writeFileSync(jsPath, jsTest);
const createdFiles = createDTsTextsFromJsFilePaths([jsPath]);
for (const dtsName in createdFiles) {
  console.log('================');
  console.log(dtsName);
  console.log('----------------');
  console.log(createdFiles[dtsName]);
}

执行测试给出结果

================
/tmp/jstest.d.ts
----------------
declare function x(): {
    a: number;
    b: () => string;
};

该函数源自类型脚本编译器 API 指南中的文档

于 2021-08-05T23:17:03.580 回答