如何configuration使用从PureScript编译的JavaScript模块的TypeScript项目?

TL; DR我想为编译的PureScript模块创buildTypeScripttypes,并将它们分发到我的npm包中。 我非常乐意手动维护这些types,我只是无法弄清楚我需要在tsconfig.json(up和downstream)和package.json中放置什么。


我有一个使用TypeScript CLI在PureScript中实现核心function的项目 ,所有这些最终都是通过npm作为JavaScript分发的。 我用一个更简单的布局创build了一个类似的项目 :

. ├── cli # TypeScript CLI project │  ├── main.ts │  └── tsconfig.json │ ├── output # Compiled PureScript modules │  └── People │  ├── externs.json │  └── index.js │ ├── src # PureScript source │  └── People.purs │ └── types # TypeScript types for PureScript modules └── People.d.ts 

src/People.purs我定义了核心function:

 module People where type Person = { name :: String } david :: Person david = { name: "David "} 

types/People.d.ts我为PureScript模块定义了TypeScripttypes,所以我可以从TypeScript中安全地使用它们:

 declare module "People" { export interface Person { name: string; } export const david: Person; } 

最后,在cli/main.ts ,我想用我定义的TypeScripttypes导入已编译的PureScript模块:

 import * as People from "People"; console.log(People.david); 

我可以得到这个构build,但是当我尝试运行最终的JavaScript( node cli/main.js )时,由tsc生成的require调用失败,因为它们不使用绝对path – require("People")应该是在这种情况下require("./People") 。 在TypeScript中进行import语句可以解除types的关联。

我很难达到这些目标:

  • 对于从TypeScript导入的所有PureScript模块,保留TypeScripttypes。
  • 确保TypeScript typechecks。
  • 确保在运行时require调用PureScript模块。
  • 使用npm包分发TypeScripttypes,以便TypeScript使用者也可以使用这些types。

如果您有经验需要TypeScript的PureScript模块,并通过npm分发所有这些,我真的很感激一些指导!

你的Purescript模块被称为“人”,但应该是“人”。 我认为用相对path导入你可能会部分地在那里,但我不认为有这样的事情在d.ts文件中的相对pathinput。

我检查了你的项目, allowJs命名模块,然后我设置allowJs为true,并键入模块内联:

 import * as OutputPeople from "../output/People"; type Person = { name: string; }; type PeopleModule = { david: Person } const People: PeopleModule = OutputPeople console.log(People.david); 

我把我的修改在这里的分支: https : //github.com/justinwoo/ps-js-ts-interop/commit/fc7c1239f9d1bac1cf2bea35f7a07d30c46a5f64

如果您确实需要使用绝对path来请求您的PureScript包(例如import * as People from 'People' ),那么我认为您需要绕过节点模块parsingalgorithm(将PureScript输出放置在node_modules子目录中./output ,例如)。

但是,如果这不是那么重要,你可以用相对导入(比如import * as People from './People' ),你可以执行以下操作:

  1. 对于PureScript模块使用相对导入:

    CLI / main.ts:

     import * as People from './People'; 
  2. 将您的PureScripttypes与您的TypeScript源码放在一起:

     . ├── People │  └── index.d.ts ├── main.ts └── tsconfig.json 
  3. 将您的PureScripttypes更改为本地模块声明而不是全局:

    CLI /人/ index.d.ts:

     export interface Person { name: string; } export const david: Person; 
  4. 现在,要使它与Node模块parsing一起工作,您需要将来自两个编译器的JS输出放在同一个目录中。 我们还希望TypeScript为我们的TS文件发布types声明(在npm上发布时可以使用)。 我们还删除了paths TS编译器选项(不再需要),并为节点types添加全局types引用。

    CLI / tsconfig.json:

     { "compilerOptions": { "target": "es5", "lib": ["es2015"], "moduleResolution": "node", "baseUrl": ".", "outDir": "./../output", "types": [ "node" ], "declaration": true }, "include": [ "*.ts" ] } 
  5. 几乎完成。 现在,我们需要确保PureScript模块的types定义最终在输出目录中可供使用。 当生成types定义输出时,TypeScript将不会在其输出中复制.d.ts文件(因为这些文件不是由TS编译器创build的) – 我们需要对其进行补偿。 我不知道这是否是最好的(甚至是一个好的方法)来实现这一点,但下面的工作对我来说:

    的package.json:

     "scripts": { "build": "pulp build && tsc -P cli/tsconfig.json && cd cli && rsync -am --include='*.d.ts' -f 'hide,! */' . ./../output" }, ... 
  6. 最后但并非最不重要的,我们需要指定JS的入口点和npm使用者的types定义:

    的package.json:

     "main": "output/main.js", "typings": "output/main.d.ts", "files": [ "output/" ] ... 

我相信这并不包括创build一个混合语言和混合types的npm包的所有细节,但希望这可以作为一个起点。

声明命名空间而不是模块使一切正常。 例如,在types/People.d.ts

 declare namespace People { export interface Person { name: string; } export const david: Person; } export = People; export as namespace People; 

在编译PureScript模块之后,在编译TypeScript之前,我将cp types/People.d.ts output/People/index.d.ts 。 这使得TypeScript代码对于相同的绝对导入(例如import * as People from "People";很满意,并且TypeScript库也可以在没有额外configuration的情况下看到这些types。

但仍有一些问题:

  • 我仍然必须在已编译的TypeScript中使用PureScript模块导入(在生成后步骤中预先加上../ )。 但是,我的图书馆消费者并不需要这样做,因为它通过npm ,神奇地使它工作。
  • 我无法弄清楚如何导出带句点的命名空间,所以像Data.Maybe这样的模块就像Data.Maybe这样的命名空间。
  • 我不太了解名称空间与模块,所以可能还有其他的注意事项。