该错误确实很奇怪。
在某个时候,我开始收到由include
typescript2
config的include
选项和项目tsconfig.json
引起的怪异错误。
我什至不再了解它是如何工作的,它是覆盖还是连接或是什么?
然后,我决定需要调试该数组以检查最终到达的数组
我的rollup-plugin-typescript2
配置:
typescript2({
clean: true,
tsconfigDefaults: {
....
include: [path.resolve(__dirname, 'styles.d.ts')],
}
}),
我的tsconfig.json
配置:
...
"include": ["src", "declaration.d.ts"]
}
结果是
正如我之前所说,我开始调试它,每次都会给您带来一些尴尬的结果。
实际上,它并没有连接这些属性,而是替换了索引单元中的值,这简直令人惊讶,并且恶化了开发人员的经验。
我的意思是说:
它将我的tsconfig
数组的索引取0并将其放在typescript2
config的0索引下。
范例1:
typescript2: ['a']
tsconfig: ['b', 'c']
result: ['b', 'c']
范例2:
typescript2: ['a', 'd']
tsconfig: ['b', 'c']
result: ['b', 'c']
范例3:
typescript2: ['a', 'd', 'e']
tsconfig: ['b', 'c']
result: ['b', 'c', 'e']
太烦人了
我不确定这是否相关,但是
节点:13.13.0
作业系统:macOS Catalina 10.15.4
这使使用include
不可能,因为您永远不知道tsconfig.json
的数组将有多长时间
有趣的是,
如果我将typescript2
config include
选项从tsconfigDefaults
移到tsconfigOverride
它将按索引覆盖原始的tsconfig.json
include
选项。
也就是说,恰恰相反
但这也很糟糕
还有一件事
经过一些额外的调查
我意识到相同的行为也与其他数组属性相关
所以我之前在https://github.com/jaredpalmer/tsdx/pull/666#discussion_r404847759中遇到了这个问题,对于每个问题,这就是_.merge
的深度合并的工作方式。 这是一次深度合并,因此它将合并数组,而索引是数组的唯一标识符。 可能是_unexpected_,但它是深度合并,这就是深度合并的工作方式。
实际上,它不会连接这些属性,而是替换索引单元格中的值,
tsconfig
覆盖。 对我来说,这似乎是错误的行为。tsconfig
对于exclude
:如果添加一个exclude
,它将覆盖默认值。我可以编写PR来对include
和exclude
进行浅层合并,但这将_pretty_破坏了更改; 我不知道这将如何影响所有下游用户。 如果TSDX用户期望浅合并或深合并,则为Idk,但是如果期望深合并,则将破坏其用法。
如果我将
typescript2
configinclude
选项从tsconfigDefaults
移到tsconfigOverride
它将按索引覆盖原始的tsconfig.json
include
选项。也就是说,恰恰相反
是的,这就是tsconfigOverride
工作方式,它是一个替代。
我意识到相同的行为也与其他数组属性相关
是的,这就是_.merge
进行深度合并的方式,因此tsconfig
中的任何数组都具有相同的更改。
@ agilgur5感谢您的回复!
1)从我的角度来看,此行为使配置完全无用。 如果我们绑定到阵列中的某个位置,我们将无法保证配置的可靠性。
2)确实,这将是一个重大突破。 但是,如果我们的方向是获得最佳DX ,那么我们应该使这件事变得清楚和有用。
我口袋里有个技巧来处理这个问题,但是从干净的代码角度来看,它看起来很嘈杂-只需阅读tsconfig
,获取include
属性并将其与我的数组连接即可。 看起来应该更简单。
我的建议:
1)默认-收集默认属性并与原始tsconfig连接; 删除重复项。
2)覆盖-仅应用覆盖选项
缺省值通常在被覆盖时不会串联,它们会被覆盖。 正如我上面提到的,串联使_impossible_可以使用tsconfig
覆盖默认值。 对于我来说,这听起来是错误的,有多种方式,所以我强烈建议不要这样做。
我认为所有选项都令人困惑,我不确定我是否同意其中任何一个都是“最佳DX”。 浅表合并是tsconfig
与默认值exclude
一起工作的最接近的方法,但这并非没有取舍。
通常,需要对重大变化进行很多思考,这就是我提出这一点的原因-下游影响不小。 TSDX还必须发布重大更改以更新为此类更改。
@ agilgur5很好,那么我完全不能使用默认值或替代值。
原因? 无法保证不会在该索引上写入任何值。
另外,您可以通过undefined作为数组的值来解决所有问题,并进一步添加所需的值。 事实证明,该系统存在差距吗? 太好了
案子:
d.ts
。src
目录放在“ include”内,并在src
之外键入另一个项目特定的d.ts
src
。如您所见,无法正确配置它。 我应该阅读tsconfig.json,获取其“ include”属性并将其合并到['src','some.d.ts','another.d.ts','config.d.ts']中。
我认为这是一个完整的开销。
同时,我弄清楚了问题所在。 其他人可能没有弄清楚,而是花了宝贵的时间来找出对他们不起作用的东西。
在您的第一条信息之后,我已经至少看到了2个相关问题。 而且它将继续下去。
我看到它是因为,如果我们保留一切,那么我将无法使用它,对我来说这是一个黑匣子,因为我无法保证任何事情。
没有个人喜好“喜欢” /“不喜欢”的空间。
可以使用或不使用。 而且不可能。
我毫不犹豫地收集了参与其中的其他人的意见。
还有一件事,对于当前的解决方案,我没有任何问题,我拥有上述的hack,可以随时使用。 但是我不理解使该解决方案透明化会带来什么问题,而又与必须进行重大更改这一事实无关。
我的意思是,您已经在这里给出了自己的喜好,而我已经给出了多个不同的选择。 我已经说过两次了,为什么从根本上打破了这种偏好(串联),同样没有直觉,而根本没有“透明”。 再说一遍,串联并不是一个重大的改变,它实际上使不可能的事情不可能。
事实是,不可能用连接覆盖不是“首选项”。
同样,不能覆盖的“默认”也不是默认,这是必要条件。 将“默认”更改为要求没有意义,并且是错误的行为。
您现在可以覆盖深度合并,不能覆盖串联。 使现有用例不可能是没有道理的。
我也已经两次给出了一个从根本上没有破坏的替代选项,这是一个浅层的合并。 我将再次重复,您也可以使用浅表合并来解决此问题。
这是否更好还有待商.。 一切都需要权衡。
我之前在这里做出了修复错误的贡献(我知道这是_.merge
因为我已经阅读了代码库),并且我维护的库在该库的使用中占了很大一部分(〜10%),我是不只是在这里说要说...
更不用说,这可以在不中断更改的情况下解决-您可以为tsconfigConcat
或tsconfigDefaultShallow
等添加新选项。
说只有一种选择,它必须打破并且必须使现有用例成为不可能,这是完全不正确的。
我认为无论我们在这里做什么,都必须打破常规。 为了使其按照文档和属性名称的精神行事,基本上应该这样做:
tsconfigDefaults
-这是下面所有内容都将被深深合并的对象tsconfig
-这是我们从打字稿中获取的对象,包括它自己的导入内容和所有内容。 此处的所有值替换tsconfigDefaults
。 此处的所有数组都与tsconfigDefaults
数组连接在一起。tsconfigOverride
-这是核选项。 对象仍然被深深地合并,但是这里的数组代替了批发的数组。 因此,如果您在此处提供一个空的包含数组,则最终tsconfig根本不会包含任何包含。是否可以涵盖我们要支持的所有情况(在用户进行适当更改后),还是我遗漏了一些东西?
@ezolenko听起来很棒,使用起来很有道理
@ezolenko我不确定你为什么要打破事情? 我已经给出了不间断的选项。
我不确定您列出的内容如何反映“文档和属性名称的精神”,因为文档说:
传递为
tsconfigDefaults
将与加载的tsconfig.json
合并。 传递给打字稿的最终配置将是tsconfigDefaults
的值的结果,该值将替换为已加载的tsconfig.json
[...]
这是一个深刻的合并(对象合并,阵列连接在一起,图元被替换等),增加verbosity
3,寻找parsed tsconfig
如果你得到意想不到的事情。
它说“合并”,“已替换”和“深度合并”,所有这些都意味着替换和覆盖默认值。 与“其余”有一个单独的引用,“引用”与rest_有所不同,但深度合并实际上不会并置。 5位引用者说了一件事,而第六位则说错了。 对我来说,这听起来像是错误的第6个参考,应该纠正,而不是将5个正确的参考更改为不正确的第6个参考。
lodash
是事实上的标准,它对merge的定义是_not_不能连接。 默认值的定义是,当您设置相同的属性值_not_并置时,它们将被覆盖:
_.defaults({ a: ['a'] }, { a: ['b', 'c'] });
// => {a: ['a']}
_.defaultsDeep({ a: ['a'] }, { a: ['b', 'c'] });
// => {a: ['a', 'c']}
如果您想添加一个串联选项,我认为这应该是一个单独的配置,因为它也与文档中的5个以上引用都不匹配,并且这根本不是默认值的含义,无论在定义上还是在任何用法上均不如此。图书馆。
它还使用tsconfigOverride
以及它自己的文档打破了对称性:
tsconfigOverride
:{}
参见tsconfigDefaults
。
我希望默认值会被覆盖,即定义,使它们串联起来是难以理解的。 深度合并对于数组可能并不直观,但是文档明确表示这是深度合并,由于索引是相关的,因此我很快就知道这是问题所在。 我也没有报告错误,因为这就是文档所说的,甚至链接到深度合并-这是预期的行为,而不是错误。
正如我说过的,浅合并数组可能更直观,因为这就是tsconfig
_itself_实际的工作方式。 正如我上面所链接的,当您添加exclude
时, tsconfig
_itself_不会并置,它会覆盖现有的exclude
。
因此,串联已不匹配文档中的5个以上引用,合并的定义,默认值的定义或tsconfig
自己的行为。 并且它破坏了对称性和其他选项的文档。 我不确定这是如何直观的。
正如我多次说过的那样,使其成为非常不直观的连接而不是覆盖使某些用例_impossible_成为
目的是,如果您添加自己的exclude
,它将覆盖我们设置的默认值。 仅在未设置属性名称的情况下才应用默认值,就像其他所有属性名称一样(同样,这是默认值的定义以及默认值在所有库中的工作方式)。
如果您要将其更改为连接,那么用户现在无法覆盖我们的默认exclude
,这是_impossible_ ,他们可以覆盖默认值。 我们还提供了tsconfig
的默认exclude
,因此即使tsconfig
_itself_可以让您做到这一点,也_impossible_可以覆盖tsconfig
的默认值那。
不知道为什么我要在整个生态系统_中重复_现有定义_和_现有用法_时,像破记录一样说话。
@ agilgur5
正如我多次说过的那样,使其成为非常不直观的连接,而不是覆盖
使得某些用例不可能实现。 这是TSDX的用法:
https://github.com/jaredpalmer/tsdx/blob/17ffcd215f78a4e9d6936644cbeab332f6439088/src/createRollupConfig.ts#L149 -L178
这种配置很容易被破坏,我不明白为什么这对您不明显。 我不希望我的库脆弱,这就是为什么创建此问题的原因。
有趣的是, @ ezolenko和我已经提出了一种可以保护包括TSDX在内的解决方案,但是您仍然会抵制。
仅在未设置属性名称的情况下才应用默认值
我同意默认行为。 仅当tsconfig没有相应的属性时才应用config default是有意义的,但这会引起许多其他更复杂的问题,其解决方案将使API变得过于复杂。
他们无法覆盖默认值
问题是,用户为什么应该有权访问图书馆作者禁止的内容?
我们必须具有无法覆盖的tsconfig配置,但与此同时,我们需要有机会对预设进行扩展。 这是重点。
解决方案仅在于新API的设计。
这种配置很容易被破坏,我不明白为什么这对您不明显。 我不希望我的库脆弱,这就是为什么创建此问题的原因。
您是从我口中说出我没说过的话。 我没有说它不能,也没有说它不脆弱。 我只是说_your_解决方案与默认值_整个生态系统_中的
正如我已经说过几次,我的建议是改为浅合并数组,即tsconfig
覆盖tsconfigDefaults
因为它对每个非数组属性都有效,并且tsconfig
_itself_起作用。
正如我多次说过的那样,可以通过进行重大更改或不进行更改来完成此操作。
请不要说出我的话。 我已经重复了无数次,请阅读我写的实际内容,而不是虚构内容。
问题是,用户为什么应该有权访问图书馆作者禁止的内容?
tsconfig
也不禁止,TSDX也不禁止,而rollup-plugin-typescript2
也不禁止,所以我不知道您指的是什么。
我们必须具有无法覆盖的tsconfig配置,但与此同时,我们需要有机会对预设进行扩展。 这是重点。
解决方案仅在于新API的设计。
是的,您可以为此添加一个tsconfigConcat
选项,这将是一个“新API”。 通过重新发明默认的整个定义来破坏当前的API,会产生一系列新问题和新的不直观行为。 除非深度合并对于数组可能不直观,但它仍然是_correct_行为。 串联只是错误的行为,因为这不是默认值的含义。
tsconfigConcat
可以解决您的用例,并且更直观,因为它的名称实际上具有concat,这正是它的作用。
将tsconfigDefaults
更改
默认= \ =串联。 那不是我的意见,而是定义。
@ agilgur5对不起,但您不能当真。
您的每句话都是有争议的,我已经厌倦了。
我只是争辩说,当前的API根本不允许对其进行任何适当的工作,这就是更改它的原因。
我不再继续了。
好吧,我没有从别人的嘴里吐出来的话,没有读过他们的真实话,没有编造东西,攻击贡献者的性格,提供0个链接,提供0个选择,只考虑一个选项而没有其他选择,那就是你。
如果您想攻击只是试图提供帮助并提供真实定义,真实用例和真实替代品的贡献者,那么我想这就是您的冒犯:shrug:
我想我印象很深,lodash合并实际上在我编写该部分时会合并数组(交错它们或其他东西)。 或者,我什至都不在意数组发生了什么。 由于它显然使用索引作为元素名称覆盖了数组的内容(对吗?这是关于数组的JavaScript最初不是真正的数组,而是字典中恰好有键的数字吗?),因此,我们现在的文档位于其中。
理想情况下,默认/主要/替代tsconfigs选项应允许以相同的毫不奇怪的方式自定义所有参数(标量值和数组)。 Lodash基于索引替换数组元素的方式有一个主要缺点-您无法创建文字稀疏数组(也许是用undefined
s填充数组?)。 这意味着必须动态构建汇总配置,而作为json文件的tsconfig根本无法执行。
即使使用文字稀疏数组,基于索引替换元素也太脆弱了。
另一方面,如果通常没有其他行为,则串联是令人惊讶的。 并且单独不允许删除以前的值。
我最初提出的在连接和替换之间进行切换令人惊讶。
像@ agilgur5所建议的那样,更改两个合并以替换批发的数组可能是一个最不意外的选择,它将允许删除值,但以不得不重复一个想要保留的值为代价。 不过,这仍然是一项重大突破,人们将不得不为此重写其配置(请参阅https://xkcd.com/1172/)。
我们可以更改这些选项的行为,也可以创建新的集合并使用警告来弃用现有的选项。
(对不起,如果我错过了某个重要的观点,我只会跳过整个主题)
@ezolenko我明白了
让我们看一下情况和动机:
开发人员希望通过汇总插件为打字稿添加一些必要的配置。
在这种情况下,我们不应该阻止开发人员安全地添加设置,并且在合并配置和汇总配置时也不要丢失任何其他设置。
这告诉我们什么? 让我们从语义开始:
正如我之前所说
我同意默认行为。 仅当tsconfig没有相应的属性时才应用默认配置。
我们可以完全重新设计这个东西。
我的建议是:
tsconfig
没有对应的属性时,应用tsconfigDefaults
属性。tsconfigOverride
应该注意这一点。我只是想避免使用第三个附加的rpt2选项,因为它将使该API复杂至少50%,并且任何开发人员都将不再理解这一点。
@ agilgur5现实与您说的话不是
另外,由于有了电子邮件通知,我阅读了原始消息,并且未编辑8次,以使人们觉得更好。
而且,没有人想要攻击您,没有人这样做。
只是被要求您停止积极进取,并停止在该主题中撰写矛盾的演讲。
@maktarsis在您的方法中,开发人员将如何从tsconfig中删除包含或排除条目? 场景是:您有一个在其他地方使用的tsconfig.json,想要在汇总中使用它而不接触json本身,但是出于某种原因,您想从excludes数组中删除一行。
@ezolenko我虽然明白你的意思。
自然地,如上所述,这将是不可能的。
但是,我们谈论的是可能性而不是动力。
我仍然看不到需要重写排除的情况。
尽管如此,我认为我们不需要覆盖dev的“排除”。 换句话说,我无法想象为什么。
有必要了解“由于某些原因”的原因。
如果您希望在任何情况下都具有这种可能性,则需要提供一个附加的API进行串联。
但是,正如您可能理解的那样,我认为它可能是无人认领的,根本就没有必要。
从“排除”中排除某些内容可能根本没有必要,但是如果我们采用其他方法,则会使对配置的理解复杂化。
我们都需要,在数组中添加一些不存在的东西,并从中删除一些东西。 使用浅层合并时,添加和删除都是通过在更高级别上复制整个数组(带有更改)来完成的。 不是很方便,但是可以使用。
"esModuleInterop": true
也是如此,这使我的库在某些环境下无法工作。
config.json中的无用编译器选项:
{
...
"compilerOptions": {
...
"esModuleInterop": true,
},
}
rollup-config中有用的编译器选项:
typescript({
useTsconfigDeclarationDir: true,
tsconfigOverride: {
esModuleInterop: true,
},
}),
@maktarsis第一个建议对我来说是预期的行为:
当原始tsconfig没有对应的属性时,请应用tsconfigDefaults属性。
^上面的注释似乎无关紧要,因为它与include
或数组无关。 提到的“建议”是tsconfigDefaults
已经完成的工作。
我和TSDX也大量使用esModuleInterop
,所以我知道它可以在tsconfig.json
,不确定该注释的含义。 发布的配置也缺少compilerOptions
,它应该是:
js
typescript({
useTsconfigDeclarationDir: true,
tsconfigOverride: {
compilerOptions: {
esModuleInterop: true,
},
},
}),
但这将覆盖并按预期工作。
此处注意到此回购中先前曾多次提及浅层合并:#86(如我在此处所述,提到了TS的浅层合并行为), https://github.com/ezolenko/rollup-plugin-typescript2/issues/72 #issuecomment -383242460和https://github.com/ezolenko/rollup-plugin-typescript2/issues/208#issuecomment -594237841
最有用的评论
我认为无论我们在这里做什么,都必须打破常规。 为了使其按照文档和属性名称的精神行事,基本上应该这样做:
tsconfigDefaults
-这是下面所有内容都将被深深合并的对象tsconfig
-这是我们从打字稿中获取的对象,包括它自己的导入内容和所有内容。 此处的所有值替换tsconfigDefaults
。 此处的所有数组都与tsconfigDefaults
数组连接在一起。tsconfigOverride
-这是核选项。 对象仍然被深深地合并,但是这里的数组代替了批发的数组。 因此,如果您在此处提供一个空的包含数组,则最终tsconfig根本不会包含任何包含。是否可以涵盖我们要支持的所有情况(在用户进行适当更改后),还是我遗漏了一些东西?