如何从现有的JavaScript库生成.d.ts“typings”定义文件?

时间:2012-10-02 09:29:03

标签: typescript tsc

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

9 个答案:

答案 0 :(得分:200)

根据所涉及的库,编写方式以及您正在寻找的准确度,有几种选择可供选择。让我们按照可取性的大致降序来审查这些选项。

可能它已经存在

请先检查DefinitelyTyped(https://github.com/DefinitelyTyped/DefinitelyTyped)。这是一个完整的数千个.d.ts文件的社区回购,很可能你正在使用的东西已经存在。 您还应该检查TypeSearch(https://microsoft.github.io/TypeSearch/),它是NPM发布的.d.ts文件的搜索引擎;这将比DefinitelyTyped稍微多一些定义。 一些模块也将自己的定义作为NPM发行版的一部分进行发布,因此在尝试编写自己的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";

这将允许import "foo"模块使用any类型。如果您想要稍后处理全局,只需编写

即可
declare const foo: any;

将为您提供foo变量。

答案 1 :(得分:38)

您可以像Ryan描述的那样使用tsc --declaration fileName.ts,也可以在declaration: true compilerOptions下指定tsconfig.json,假设您已经拥有tsconfig.json在你的项目下。

答案 2 :(得分:15)

处理此问题的最佳方法(如果DefinitelyTyped上没有声明文件)是仅为您使用的内容而不是整个库编写声明。这大大减少了工作量 - 此外,编译器可以通过抱怨缺少方法来帮助解决问题。

答案 3 :(得分:12)

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

答案 4 :(得分:7)

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

答案 5 :(得分:2)

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

如果不这样做,将第三方lib的C#公共接口转换为TypeScript定义可能比通过阅读源JavaScript更简单。

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

答案 6 :(得分:2)

以下是一些PowerShell,它创建一个TypeScript定义文件库,其中包含带有现代JavaScript的多个*.js文件。

首先,将所有扩展名更改为.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文件结尾,其中包含许多定义。

答案 7 :(得分:0)

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

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

(有关所有命令行编译器选项,请参见docs

或者例如在您的package.json中:

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

然后运行:yarn build:types(或npm run build:types

答案 8 :(得分:0)

此答案显示了如何使用 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;
};

函数派生自documentation in the type script compiler API guide