typescript - 如何让 TSLint 解决与 Yarn 工作区的间接类型依赖关系?

标签 typescript yarnpkg tslint yarn-workspaces

上下文

workspaces提供一种方便的方式来依赖单库中的包。当包A依赖于包B时,包B中定义的接口(interface)等在包A中被适本地解析。

问题

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

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

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 依赖于包 camelcase ,或者 X 或 Y。它只应该知道包 B 的公共(public) API,即 dependedFn

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

最佳答案

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

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

这些行告诉 TypeScript 编译器和 TSLint,当您导入它们时,它们不应将您的模块 ab 视为包,而是它们应该使用以下方法解析单个 TypeScript 文件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 使用 TypeScript 编译器 API 根据 tsconfig.json 中的规则进行检查。但是您的 TypeScript 编译器不使用 tsconfig.json 规则。在实际项目中,这两个命令都将使用 tsconfig.json

当你也开始使用 tsconfig.json 进行编译时,你会遇到与使用 TSLint 时一样的解决二度依赖类型的问题:

$ 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'
                    ~~~~~~~~~~~

发生这种情况是因为路径映射模块导入按设计不同编译,然后根据 TypeScript 文档从 node_modules 正常导入 https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping 如答案第一部分所述。

我建议在您的项目中使用普通导入,以免工具出现问题:

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

关于typescript - 如何让 TSLint 解决与 Yarn 工作区的间接类型依赖关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51430563/

相关文章:

typescript - TSLint:未使用的 var 关键字

angular - 将angular 9升级到10后如何更新eslint的配置

javascript - 是否可以将变量值用作 Typescript 中的联合类型之一?

typescript - JSX 元素类型 'HTMLImageElement' 不是 JSX 元素的构造函数

Webpack 和 Yarn 工作区/Lerna

webpack - 在 Vue.JS SPA 中添加包的正确方法

typescript - Angular2 NgFor 在组件内

javascript - Typescript 接口(interface)中的输入类型

ruby-on-rails - Yarn Registry 总是返回 503 Unavailable

angular - 安装 angular2-notifications 后运行 lint 失败