你好,我们又见面了,
我不确定这是问题还是设计决定,但我可以看到规则no-inferrebale-types
和typedef
之间的冲突。
前任。
function fn(): void {
for (let i = 0; i < 100; i++) {
console.log(i);
}
}
来自https://github.com/palantir/tslint/blob/master/docs/sample.tslint.json的片段:
"typedef": [true, ...],
"no-inferrable-types": true,
当我打开这两个规则时,我得到:
error (typedef) test.ts[2, 12]: expected variable-declaration: 'i' to have a typedef
将类型注释number
添加到变量i
会依次导致以下错误:
error (no-inferrable-types) test.ts[2, 14]: LHS type (number) inferred by RHS expression, remove type annotation
有没有办法让这两个规则共存?
例如,我想用原始类型直接声明可推断变量(如规则文档所说: number
、 boolean
或string
),但另一方面,我想要在非原始类型上强制使用 typedef。
谢谢,
O。
很好的收获,感谢您的提醒。 我添加了no-inferrable-types
规则,没有考虑它可能与typedef
规则冲突,哎呀! 现在我建议关闭两者之一,或者只使用typedef
规则的一些选项。
从长远来看,我认为我们要么希望将no-inferrable-types
集成到typedef
规则中,要么我们希望至少让 TSLint 检测冲突配置,例如同时启用这两个规则。
我面临同样的问题。
我现在已经关闭了 no-inferrable-types。
是的,这里也一样,我希望有能力让这两个规则共存。
如果可以推断出变量的类型,我不希望 typedef 规则生效。
即“no-inferrable-types”应该优先于“typedef”
+1
let id: number = 0;
for (let job: string of NAMES_PROFFESSIONS) {
/** some code */
id++;
}
(no-inferrable-types) LHS 类型(数字)由 RHS 表达式推断,去掉类型注释
+1
您对“可推断”类型的定义是否包括构造函数赋值?
// BAD (this hurts my eyes to read)
let labels: Map<string, string> = new Map<string, string>();
// GOOD (type is obvious)
let labels = new Map<string, string>();
但是也...
// BAD (in a diff, it's not obvious what this type is)
let labels = this.buildLabels();
// GOOD
let labels: Map<string, string> = this.buildLabels();
是的,这很危险。 如果我想简化我的代码并防止对直接初始化的变量使用类型声明,我不能严格这样做,这会带来这样的事情:
let x = 2;
let y;
let z: number;
x = 1;
y = 1;
z = 1;
x = 's'; // Type 'string' is not assignable to type 'number'
y = 's'; // It's OK
z = 's'; // Type 'string' is not assignable to type 'number'
仅允许对初始化变量进行跳过类型声明可能是一个非常有用的选项。
... 正如@pgonzal所说,实际上不仅适用于原始类型!
看看这个,太可怕了:
const onChange: () => void = () => this.update();
:+1: 理想情况下(imo)我想说“总是需要 typedef,除非类型是可推断的”。 我认为现在不可能。
我遇到了这个问题并制作了一个ignore-params
标志,这对我的情况有所帮助。 我想对所有方法/函数参数强制使用 typedef,即使它们可以很容易地推断出来。
如果您想尝试一下,请参阅 PR:#1190
自从提交原始问题以来已经有一段时间了。 此时推荐选项是否禁用no-inferrable-types
并在所有内容中包含类型? 尝试启用和组合no-inferrable-types
和typedef
的任何其他操作似乎都是一种 hack,并导致一堆毫无意义的警告。 希望在不久的将来有更好的解决方案。
@corydeppen请注意上面对@englercj建议的 8 个竖起大拇指。 目前尚不清楚您的“似乎是黑客”评论中的“组合”是什么意思。 如果您的意思是“在tslint.json
中一起使用,那么,是的。但是在typedef
上“组合”一个optional-inferrable-types
参数会很棒(至少,对于我们中的 9 个人来说)。
请问我们可以得到这方面的更新吗?
我认为处理此问题的最佳方法是弃用no-inferrable-types
并将选项对象传递给typedef
以忽略类型定义的缺乏,如果根据某些模式可以推断类型,如initialized
、 initialized primitives
、 call signatures
和其他可以满足我们开发人员需求的模式。
对我来说,这更有意义,因为应该总是有一个 typedef,除非有东西告诉你它是函数的类型。 而且它也是可配置的,因为,也许我们希望类中初始化的properties
具有可推断的类型,但对于call signatures
来说却不是这样。
如果有人能帮忙解决这个问题,那就太好了。 在那之前,我们被迫在“没有足够的类型声明可读”和“杂乱无章的类型声明”之间做出选择。
这个问题自 2015 年 10 月 3 日以来一直开放——从那时起,我的团队已经编写了大约 2000 个 TypeScript 源文件,这些文件都包含太多的类型声明。
typedef
接受配置。 因此,如果类型是可推断的,则可能只是另一种配置来忽略类型定义,这意味着
只需在未初始化的地方键入。
看起来是因为在如何处理这个问题上没有明确的共识,所以没有取得任何进展。 示例评论: https ://github.com/theia-ide/theia/issues/356#issuecomment -319350833
我怀疑我们都同意任何解决方案都比保持现状更好。 如果您认为在这个问题上对现状的任何改变都是好的,请👍这个评论。 如果您有足够的知识创建 PR 来解决此问题,请帮助我们所有人❤️。
将接受 PR 以:
typedef
添加一个选项,让它忽略no-inferrable-types
表示不提供类型的情况typedef 接受一个配置。 因此,如果类型是可推断的,则可能只是另一种配置,只是忽略类型定义,这意味着“只需在未初始化的地方键入即可。”
typedef
规则适用于喜欢在代码库中明确类型定义的人。 如果您希望上述行为“只在未初始化的地方键入”,则最好禁用typedef
并确保将noImplictAny
启用为 TypeScript 编译器选项。
还有一个棘手的情况是,一些初始化的东西无论如何都需要 typedef,如下面的代码片段所示:
interface Literal {
field: "value"
}
const literal0 = {
field: "value",
};
const literal1: Literal = {
field: "value",
};
const func = (obj: Literal) => { };
func(literal0); // Error! Type 'string' is not assignable to type '"value"'.
func(literal1);
此外,虽然我们解决了这个问题,但想提一下,可能有一些很棒的第 3 方规则,比如no-unnecessary-type-annotation
(https://github.com/ajafff/tslint-consistent-codestyle/blob/ master/docs/no-unnecessary-type-annotation.md)例如。 如果有人知道提供所需行为的任何其他 3rd 方规则,请在此处发布它们,我们可以正式推荐它们或在有意义的情况下将它们纳入核心。
@JKillian感谢您的推荐,我认为这实际上就是我想要的。 有一篇关于避免any
类型的非常好的帖子:不要使用“naked any”,而是创建一个“any interface”。
关于:
interface Literal {
field: "value"
}
const literal0 = {
field: "value",
};
const literal1: Literal = {
field: "value",
};
const func = (obj: Literal) => { };
func(literal0); // Error! Type 'string' is not assignable to type '"value"'.
func(literal1);
我不明白这怎么可能是不受欢迎的行为,也不是一个棘手的案例。 您要确保obj
$ 具有价值value
的属性field
$ ,即使您使用看起来像约束的属性初始化literal0
,您可以将其修改为另一个字符串。
我知道这不是一个好的用例,但大多数情况下,当您使用文字时,您可能需要该文字,而不是原语。
我有以下配置:
json
"no-inferrable-types": true,
"typedef": [true, "call-signature", "parameter"],
而这段代码:
javascript
private static readonly DEVICE_UID: string = 'device_uid';
private static readonly DEVICE_PLATFORM: string = 'browser';
private static readonly AGENT_DEFAULT_ICON = 'http://localhost:3000/icon.png';
为什么我在前两个声明中没有出错?
@sandrocsimas 很有趣,但我认为离题了; AFAICT,该问题与此问题无关。 我建议你开始另一个问题(fwiw!)。
@estaub ,是的,我会的。 即使没有 typedef 规则,我也会得到相同的行为。
@sandrocsimas那是因为它是一个只读属性,并且这样的 Typescript 将其类型推断为文字。 将其键入为字符串,您告诉它应该有一个字符串,它不一定具有该文字值,并且该值不应静态更改。
有一个“require-typedef-except-inferrable”规则会很好。
@FiretronP75正如@JKillian所说,这只是 TSC 的noImplicitAny
选项。
@michaeljota谢谢,我没有意识到编译器的noImplicitAny
选项提供了可推断的异常。 尽管如此,在 tslint 中仍然会很好,因为可以选择将其作为警告而不是破坏编译,并且可以使用 tslint 注释标志。
我明白为什么需要这样做,但是以no-unused-variables
为例,我认为 TSC 涵盖的用例不会得到 TSLint 团队的支持。 我知道_linter error_ 与_compiler error_ 不同,但最后,它们都是关于编写更好的代码。 现在有了 Webpack 或 Parcel 等解决方案,即使出现 TSC 错误,您也可以编译和运行代码,我不认为这是一个真正的问题。
这个问题在最新版本中修复了吗?
我仍然认为这不在路线图上。 您应该考虑使用来自 TSC 的noImplicitAny
☠️ TSLint 的时间到了! ☠️
TSLint 不再接受每个 #4534 的大多数功能请求。 请参阅typescript-eslint.io了解使用ESLint对 TypeScript 代码进行 lint 的新方法。 ✨
很高兴与大家一起开源!
🤖哔哔! 👉 TSLint 已弃用👈 _(#4534)_ 你应该切换到typescript-eslint ! 🤖
🔒 此问题已被锁定,以防止进一步不必要的讨论。 谢谢! 👋
最有用的评论
:+1: 理想情况下(imo)我想说“总是需要 typedef,除非类型是可推断的”。 我认为现在不可能。