由于任何关键字导致的Typescript esint和strict_check错误



下面的代码片段,带有解释代码的注释。

// The function here is to check whether the two arguments are equivalent or
// not empty or not. So, we cannot have any specific type defined for the
// arguments and the arguments are given a generic type of Object.
/**
* @param {Object} a - the first object to be compared.
* @param {Object} b - the second object to be compared.
* @return {boolean} - true if a is equivalent to b, false otherwise.
*/
isEquivalent(a: Object, b: Object): boolean {
if (a === null || b === null) {
return a === b;
}
if (typeof a !== typeof b) {
return false;
}
if (typeof a !== 'object') {
return a === b;
}
// Create arrays of property names.
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
if (aProps.length !== bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
if (!this.isEquivalent(a[propName], b[propName])) {
return false;
}
}
return true;
}

我使用typescript检查--strict_checks运行此程序,它会给我以下错误消息:错误TS7053:元素隐式具有"any"类型,因为类型为"string"的表达式不能用于索引类型为"Object"。在"Object"类型上找不到具有"string"类型参数的索引签名

当我将for循环修改为以下内容时:

for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
const aObj: {[index: string]: any} = a;
const bObj: {[index: string]: any} = b;
if (!this.isEquivalent(aObj[propName], bObj[propName])) {
return false;
}
}

--strictcheck错误已修复。然而,我现在收到打字脚本esint错误,因为使用了关键字"任何";在eslint中被禁止。有人能在不禁用检查的情况下为我指出绕过这些错误的正确方向吗?

您不应该使用Object作为类型。您可以使用object(请参阅此处的文档(,但在使用循环和访问属性时仍然会出现any-错误,因为object是不可索引的。解决方案是提供您自己的界面:

interface IndexableObject {
[key: string]: string | IndexableObject
}

假设您正在比较的对象可能是递归的,您可以将IndexableObject的值定义为字符串,也可以将其本身定义为另一个IndexableObject

导致错误的另一件事是,您正在检查a是否是对象,而不是b是否也是对象。编译器会抱怨,因为您以后可能会访问字符串,就好像它是一个对象一样(a[propName/b[propName](。虽然这确实有效,但因为在JS中,所有都是一个对象(因此'foo'[0]将产生"f"(,TypeScript编译器不会喜欢它。所以你也应该检查一下。

有了这些更改,您的功能将按预期工作:

interface IndexableObject {
[key: string]: string | IndexableObject
}
// The function here is to check whether the two arguments are equivalent or
// not empty or not. So, we cannot have any specific type defined for the
// arguments and the arguments are given a generic type of Object.
/**
* @param {Object} a - the first object to be compared.
* @param {Object} b - the second object to be compared.
* @return {boolean} - true if a is equivalent to b, false otherwise.
*/
function isEquivalent(a: IndexableObject | string, b: IndexableObject | string): boolean {
if (a === null || b === null) {
return a === b;
}
if (typeof a !== typeof b) {
return false;
}
if (typeof a !== 'object' || typeof b !== 'object') {
return a === b;
}
// Create arrays of property names.
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
if (aProps.length !== bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
if (!isEquivalent(a[propName], b[propName])) {
return false;
}
}
return true;
}
const ex1 = { 'foo': 'bar' };
const ex2 = { 'foo': 'bar' };
const ex3 = { 'foo': 'foo' };
const ex4 = { 'foo': { 'foo2': 'foo3' } };
const ex5 = { 'foo': { 'foo2': 'foo3' } };
const ex6 = { 'foo': { 'foo2': 'foo4' } };
console.log(isEquivalent(ex1, ex2)); // true
console.log(isEquivalent(ex1, ex3)); // false
console.log(isEquivalent(ex4, ex5)); // true
console.log(isEquivalent(ex4, ex6)); // false

顺便说一句,如果你的项目中有Lodash,他们已经很好地解决了这个问题。这是我的经验;滚动自己的";更有趣,但你迟早会遇到其他人已经处理过的边缘案例,在这一点上,乐趣几乎停止了。不过那只是我的0.02美元。

最新更新