上下文
纱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,当您导入它们时,它们不应将您的模块 a
和 b
视为包,而是它们应该使用以下方法解析单个 TypeScript 文件baseUrl
和 paths
参数,然后编译各个 TypeScript 文件。此行为记录在 TypeScript 文档的模块解析 -> 路径映射部分:
https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping
相反,如果我没理解错的话,您希望将 a
和 b
视为独立的包。为此,您应该删除路径映射,然后 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
如答案第一部分所述。
我建议在您的项目中使用普通导入,以免工具出现问题:
- 在工作空间根
package.json
中有 - 在工作区包中有
"watch": "tsc -p tsconfig.json -w"
。 - 每当您对项目进行更改时 - 通过在工作区根目录中运行
npm run watch
以监视模式在每个包中启动 TypeScript 编译器。
"watch": "lerna run --parallel -- watch"
脚本
关于typescript - 如何让 TSLint 解决与 Yarn 工作区的间接类型依赖关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51430563/