我使用了很多自己的和第三方的库。我看到“typings”目录包含一些Jquery和WinRT…但它们是如何产生的呢?


有一些选项可供您选择,这取决于所讨论的库,它是如何编写的,以及您正在寻找的准确性级别。让我们大致按可取性降序来回顾一下这些选项。

也许它已经存在了

Always check DefinitelyTyped (https://github.com/DefinitelyTyped/DefinitelyTyped) first. This is a community repo full of literally thousands of .d.ts files and it's very likely the thing you're using is already there. You should also check TypeSearch (https://microsoft.github.io/TypeSearch/) which is a search engine for NPM-published .d.ts files; this will have slightly more definitions than DefinitelyTyped. A few modules are also shipping their own definitions as part of their NPM distribution, so also see if that's the case before trying to write your own.

也许你不需要

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";

这将允许您导入类型为any的“foo”模块。如果你有一个以后想处理的全局变量,就写

declare const foo: any;

它会给你一个foo变量。


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


正如Ryan所说,tsc编译器有一个switch——声明,它生成一个.d。Ts文件中的。Ts文件。还要注意(排除bug) TypeScript应该能够编译Javascript,所以你可以将现有的Javascript代码传递给tsc编译器。


我会寻找支持script#或SharpKit的第三方JS库的现有映射。使用这些c#到。js交叉编译器的用户可能会遇到你现在面临的问题,并且可能已经发布了一个开源程序来扫描你的第三方库并将其转换为框架c#类。如果是这样的话,破解扫描器程序,生成TypeScript代替c#。

如果做不到这一点,将第三方库的c#公共接口转换为TypeScript定义可能比读取源JavaScript更简单。

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


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


你可以使用tsc——declaration fileName。就像Ryan描述的那样,或者你可以在tsconfig的compileroption下指定declaration: true。Json,假设你已经有了一个tsconfig。Json在你的项目。


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

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

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

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

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

最后,将所有的*.d。Ts文件到一个索引。Ts,删除导入语句并从每个导出语句中删除默认值。

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文件,其中包含许多定义。


在创建自己的库时,您可以创建*.d。ts文件使用tsc (TypeScript编译器)命令,如下所示: (假设您正在将库构建到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",
}

然后run: yarn build:types(或NPM run build:types)


这个答案展示了如何在一个独立的函数中使用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指南中的文档