如何让TSLint解决Yarn工作区的间接键入依赖关系?

时间:2018-07-19 19:36:09

标签: typescript yarnpkg tslint yarn-workspaces

上下文

纱线workspaces提供了一种方便的方式来依赖单仓库中的软件包。当程序包A依赖程序包B时,程序包B中定义的接口等将在程序包A中得到适当解析。

问题

我遇到一个问题,如果程序包B依赖于外部库,但是该外部库缺少类型,因此程序包B已创建了自己的some-library.d.ts文件。当使用tslint对程序包A进行工作时,此自定义定义文件将针对程序包B中的表达式正确解析,但对于与程序包B中的类型兼容的程序包A中的表达式则无法正确解析。

我在这里推送了此问题的简化示例:

https://github.com/tommedema/tslint-yarn-workspaces

其核心如下。

packages / a / src / index.ts

// tslint:disable:no-console

import { someDependedFn } from 'b'

export const someDependingFn = (): void => {
  const someNr = someDependedFn('pascal-case-me')
  console.log(someNr)
}

packages / b / src / index.ts

import camelCase from 'camelcase'

export const someDependedFn = (str: string): string => {
  const camelStr = camelCase(str, { pascalCase: true })

  return camelStr
}

packages / b / src / typings / camelcase / index.d.ts

// Type definitions for camelcase 5.0
// Project: https://github.com/sindresorhus/camelcase

// tslint:disable only-arrow-functions completed-docs

declare module 'camelcase' {
  export default function camelCase(
    strs: string | string[],
    options: {
      pascalCase?: boolean
    }
  ): string
}

现在,如果您将目录更改为软件包a并运行yarn build,则可以正常工作。但是,如果您运行yarn lint,它将抛出:

$ tslint -p tsconfig.json

ERROR: packages/b/src/index.ts[4, 20]: Unsafe use of expression of type 'any'.
ERROR: packages/b/src/index.ts[6, 10]: Unsafe use of expression of type 'any'.

TSLint无法识别程序包B所依赖的类型,但仅在从程序包A运行tslint时才抱怨(不期望)。在软件包B中,tslint不会抱怨(如预期)。

问题

我当然可以在软件包A中手动添加camelcase的类型,但这似乎明显违反了关注点分离:软件包A不应该知道软件包B依赖于驼峰包或X。或Y。仅应了解程序包B的公共API,即dependedFn

在使用yarn工作区时,如何设置tslint使其正确解析这些间接输入定义?

1 个答案:

答案 0 :(得分:0)

您可以通过从tsconfig.json中删除这些行来使TSLint发挥作用:

"baseUrl": "./packages",
"paths": {
  "*": ["./*/src"]
},

这些行告诉TypeScript编译器和TSLint,在导入模块时,它们不应将模块ab视为包,而应使用baseUrlpaths个参数,然后编译单个TypeScript文件。 TypeScript文档的“模块分辨率->路径映射”部分中记录了此行为:

https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping

相反,如果我理解正确,您想将ab视为独立的软件包。为此,您应该删除路径映射,然后TypeScript和TSLint将它们视为npm软件包。

更新(基于评论中的讨论)

在您的项目中,使用以下命令运行TSLint:

tslint -p tsconfig.json 但是您使用以下命令运行TSC:

tsc src/index.ts --outDir dist

您的TSLint根据tsconfig.json中的规则使用TypeScript编译器API进行检查。但是您的TypeScript编译器不使用tsconfig.json规则。在实际项目中,两个命令都将使用tsconfig.json

当您也开始使用tsconfig.json进行编译时,与使用TSLint一样,在解决2度依赖关系类型时也会遇到相同的问题:

$ tsc -p tsconfig.json
../b/src/index.ts:1:23 - error TS7016: Could not find a declaration file for module 'camelcase'. '/home/victor/work/tslint-yarn-workspaces.org/node_modules/camelcase/index.js' implicitly has an 'any' type.
  Try `npm install @types/camelcase` if it exists or add a new declaration (.d.ts) file containing `declare module 'camelcase';`

1 import camelCase from 'camelcase'
                    ~~~~~~~~~~~

之所以会发生这种情况,是因为根据设计脚本,路径映射的模块导入的编译方式有所不同,然后从node_modules正常导入 https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping 按照答案第一部分的说明。

我建议您在项目中使用常规导入,以免出现工具方面的麻烦:

  1. 在工作区根"watch": "lerna run --parallel -- watch"中拥有package.json脚本
  2. 在工作区软件包中有"watch": "tsc -p tsconfig.json -w"
  3. 每当您对项目进行更改时-通过在工作区根目录中运行npm run watch在每个程序包中以监视模式启动TypeScript编译器。