我正在使用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"
这是可能的吗?如果是的话,正确的方法是什么?谢谢!
1条答案
按热度按时间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),以讨论这一问题。