【问题标题】:How to have TSLint resolve indirect typing dependencies with Yarn workspaces?如何让 TSLint 解决与 Yarn 工作区的间接类型依赖关系?
【发布时间】:2018-07-19 19:36:09
【问题描述】:

上下文

Yarn workspaces 提供了一种方便的方式来依赖单仓库中的包。当包 A 依赖包 B 时,包 B 中定义的接口等在包 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的公共API,即dependedFn

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

【问题讨论】:

    标签: typescript yarnpkg tslint yarn-workspaces


    【解决方案1】:

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

    "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 包。

    更新(基于 cmets 中的讨论)

    在您的项目中,您使用以下命令运行 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 中有"watch": "lerna run --parallel -- watch" 脚本
    2. 在工作区包中有"watch": "tsc -p tsconfig.json -w"
    3. 无论何时对项目进行更改 - 通过在工作区根目录中运行 npm run watch,在每个包中以监视模式启动 TypeScript 编译器。

    【讨论】:

    • 很有趣,但是我如何才能真正从我的 monorepo 中受益呢? IE。包如何解决彼此的路径?
    • 他们通过 node_modules 解析路径。您的包a 依赖于package.json 中的模块bgithub.com/tommedema/tslint-yarn-workspaces/blob/…,因此Yarn 将b 作为符号链接安装到tslint-yarn-workspaces/package/node_modules。之后 tslint 和 typescript 编译器可以从那里解析b
    • 我明白了,但这会破坏在不先编译的情况下解决类型依赖关系的能力。这是为 tslint 和编辑器使用不同 tsconfig 的主要原因之一。
    • 我在你的问题中没有看到这个要求——你不想先编译。而且我看不到您在哪里为 tslint 和问题中的编辑器使用不同的 tsconfig。请澄清。我正在尝试回答您的问题。
    • 如果您认为这样更好,我可以将其添加到问题中。不过,在示例中它已经像这样工作了。我发布的 repo 是我实际设置的简化示例,它基于github.com/Quramy/lerna-yarn-workspaces-example——你可以在那里看到编辑器与编译时间的不同 tsconfig。
    猜你喜欢
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 2013-03-11
    相关资源
    最近更新 更多