typescript - TS7017 暗示任何类型 + 类型推断
问题描述
这是错误的浓缩片段:
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 仍然会抱怨。
怎么会?有什么方法可以在不进行所有类型转换的情况下完成这项工作?
解决方案
从技术上讲, Array 仍然符合 type {[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`);
}
}
推荐阅读
- asp.net-web-api - 查询字符串格式输入UserId和密码
- vb.net - 如何在 VB.Net 中将数据表列转换为字符串列表
- coldfusion - ColdFusion 计划任务是否有内置的请求超时?
- angular - 防止选择字段无限滚动(ng-select,角度)
- json - 有没有办法在弹性搜索服务的 http 正文中解析 IAM 用户凭证?
- mfc - Visual Studio 2019 对结构中的变量没有默认值提出警告
- python - 如何正确测试具有 REST API + Flask JWT 扩展的应用程序?
- c# - 无限路径路由到 ASP.NET Core 操作
- c# - 如何将一个类中的对象传递到另一个类的列表中?
- c# - 通过 JQuery 检测 iFrame SRC 更改