这是错误的压缩摘要:
export default function formatSql(this: EscapeFunctions, sqlQuery: string, values: QueryParams) {
if (isPlainObject(values)) {
console.log(values[p]); // <-- Element implicitly has an 'any' type because type 'QueryParams' has no index signature.
} else if (Array.isArray(values)) {
// ...
} else {
throw new Error(`Unsupported values type`);
}
// ...
}
QueryParams
定义为:
export type QueryParams = StringMap | any[];
export interface StringMap {
[_:string]: any,
}
因此,如果我没有记错的话,StringMap
具有“索引签名”,并且isPlainObject
定义为:
export function isPlainObject(obj: any): obj is object {
return isObject(obj) && (
obj.constructor === Object // obj = {}
|| obj.constructor === undefined // obj = Object.create(null)
);
}
因此,我认为isPlainObject
检查将排除any[]
类型,因此,values
应该被推断为StringMap
,但这不是似乎是正在发生的事情。
即使我让isPlainObject
返回obj is StringMap
,Typescript仍然会抱怨。
为什么?我有什么办法可以在不进行所有类型转换的情况下完成这项工作?
答案 0 :(得分:2)
从技术上讲,数组仍然符合类型{[key: string]: any}
。您可以通过执行const test: StringMap = [];
进行验证。 TypeScript编译器不会抱怨。因此,您首先必须排除values
是数组的可能性。
接下来,函数isPlainObject
的返回类型定义为obj is object
。这太通用了,会使您的代码块“忘记”该对象具有索引签名。它必须为obj is StringMap
。
因此,在实践中,您需要做两件事:
if
语句中,检查该值是否为数组isPlainObject
返回类型声明更改为obj is StringMap
基本上,它看起来像这样:
export function isPlainObject(obj: any): obj is StringMap {
// ...
}
export default function formatSql(values: QueryParams) {
if (Array.isArray(values)) {
// ...
} else if (isPlainObject(values)) {
console.log(values[p]);
} else {
throw new Error(`Unsupported values type`);
}
}