如何为一个babel-plugin-content-transformer目录创建Typescript模块定义?

qyyhg6bp  于 2022-12-08  发布在  Babel
关注(0)|答案(1)|浏览(235)

我正在使用babel-plugin-content-transformer加载React Native/Expo中的YAML文档目录。
我的Babel插件配置如下:

['content-transformer', {
        transformers: [{
          file: /\.ya?ml$/,
          format: 'string'
        }],
        content: [
          // Import statements ending with "content" are converted into
          // an array of imports. The array will ony include ".y(a)ml" files
          {
            dir: /texts$/,
            filter: /\.ya?ml$/
          }
        ]
      }]

这是有效的,我既可以将单个YAML作为字符串加载,也可以将整个texts目录作为对象加载。
我的问题是**如何为texts**声明类型化模块?
在我的types.d.ts中,我有这样一个:

declare module '*.yaml' {
    const data: string
    export default data
}

这对于在单独的YAML中加载是有效的。但是当我试图导入整个目录时(我已经验证了如果忽略编译器的话是有效的),这就不起作用了:

declare module 'texts' {
    const data: Record<string, string>
    export default data
}
// results in Cannot find module '../../texts' or its corresponding type declarations.
// when I try to load from "../../texts"

这是可能的吗?如果是的话,正确的方法是什么?谢谢!

csga3l58

csga3l581#

阅读文档

在下面的代码片段中,declare module '*.yaml' {...}是一个名为 * *.yaml的环境模块声明。名称*.yaml*部分是一个通配符。模块名称中的通配符是TypeScript v2.0中引入的一个功能:
TypeScript 2.0支持使用通配符(*)来声明模块名称的“系列”;这样,扩展只需要声明一次,而不是对每个资源都需要声明。
The docs on TypeScript's module resolution logic声明:
首先,编译器将尝试定位一个代表导入模块的文件。为此,编译器遵循以下两种不同策略之一:这些策略告诉编译器在哪里查找moduleA。
如果这样做不起作用,并且模块名是非相对的(在“moduleA”的情况下,它是相对的),那么编译器将尝试定位一个环境模块声明。

将文档应用于上下文

这就是事情变得令人惊讶的地方。在“后来”,它说:
相对导入是相对于导入文件进行解析的,无法解析为环境模块声明。您应该为自己的模块使用相对导入,这些模块保证在运行时保持其相对位置。
如果是这样的话,那么编译器是如何解析你的import singleFile from "../../texts/myFile.yaml"的呢?这里的路径显然包含了一个相对路径,并且解析为一个环境模块声明。

将文档与实际行为进行比较

原因是通配符功能并没有对路径解析做任何特殊的处理,它并不关心../在文件系统中的意思是“相对父”,它只看到../../texts/myFile可以用通配符解析,并且import中剩下的.yaml与环境模块声明名称中剩下的.yaml相匹配。
尝试执行以下操作:

  • import singleFile from "../../../../AAA/texts/myFile.yaml"
  • import singleFile from "/texts/myFile.yaml"
  • import singleFile from "C:\\//\\\\/myFile.yaml"

即使在文件系统上解析相对路径实际上会失败,它们也应该解析为环境模块声明。
德努埃蒙特
那么,为什么尝试执行import allFiles from "../../texts"会失败呢?这是因为在文本文件夹的环境模块声明的名称中没有通配符,所以text前面的../../意味着它不能解析为您用名称text声明的环境模块。如果您将环境模块声明命名为*text,它应该会按照您想要的方式解析。或者,您可以将您的汇入变更为import allFiles from "texts"。因为您使用建置系统(WebPack)也有自己的模块解析机制,您可能希望使用第一种方法,其中相对路径可由构建系统机器以防止其“泄漏”的方式来解释和使用,(可由其他导入以意外和令人惊讶的方式解决)。
结束语
令我感到不安的是,当前文件(2022/10/05)似乎与实际行为相矛盾:
如果这样做不起作用,并且模块名称是相对[...],那么编译器将尝试定位环境模块声明。
[...]
相对导入是相对于导入文件进行解析的,无法解析为环境模块声明。您应该为自己的模块使用相对导入,这些模块保证在运行时保持其相对位置。
我不确定我对TS编译器行为的经验理解是否100%正确,但也许文档应该这样说:
如果这不起作用,那么编译器将尝试定位环境模块声明。
[...]
相对导入是相对于导入文件进行解析的,如果该解析失败,则会尝试解析为环境模块声明。您应该对自己的模块使用相对导入,这些模块保证在运行时或由调用TS编译器的生成系统进行解析时保持其相对位置。
也许文档中的这些条款早于通配符的添加,需要更新以澄清通配符存在时的行为。我已经在TS网站上提出了an issue ticket (#2559),以讨论这一问题。

相关问题