13

语境

Yarn工作区提供了一种方便的方式来依赖单存储库中的包。当包 A 依赖包 B 时,包 B 中定义的接口等在包 A 中得到适当的解析。

问题

我面临一个问题,如果包 B 依赖于外部库,但该外部库缺少类型,因此包 B 创建了自己的some-library.d.ts文件。使用tslintlint 包 A 时,此自定义定义文件会正确解析包 B 中的表达式,但不适用于包 A 中使用包 B 中的类型的表达式。

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

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

它的核心如下。

包/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)
}

包/b/src/index.ts

import camelCase from 'camelcase'

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

  return camelStr
}

包/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
}

现在,如果您将目录更改为 packagea并运行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 没有抱怨(如预期的那样)。

问题

当然,我可以手动添加camelcase包 A 内部的类型,但这似乎明显违反了关注点分离:包 A 不应该知道包 B 依赖于包 camelcase 或 X 或 Y。它只应该了解包 B 的公共 API,即dependedFn.

如何设置 tslint 以便在使用纱线工作区时正确解析这些间接类型定义?

4

1 回答 1

1

您可以通过从以下内容中删除这些行来使 TSLint 在您的情况下工作tsconfig.json

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

这些行告诉 TypeScript 编译器和 TSLint,当您导入它们时,它们不应该将您的模块ab包视为包,而是应该使用baseUrlpaths参数解析各个 TypeScript 文件,然后编译各个 TypeScript 文件。此行为记录在 TypeScript 文档的 Module Resolution -> Path Mapping 部分中:

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 使用 TypeScript 编译器 API 根据来自tsconfig.json. 但是您的 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_modulesTypeScript 文档 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 编译器。
于 2018-07-24T10:43:17.133 回答