【问题标题】:TS7017 implict any type + type inferenceTS7017 隐式任何类型 + 类型推断
【发布时间】:2018-07-31 08:33:35
【问题描述】:

这是错误的精简 sn-p:

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 仍然会抱怨。

怎么会?有什么方法可以在不强制转换所有内容的情况下完成这项工作?

【问题讨论】:

    标签: typescript type-inference


    【解决方案1】:

    从技术上讲,数组仍然符合{[key: string]: any} 类型。您可以通过const test: StringMap = []; 来验证这一点。 TypeScript 编译器不会抱怨。所以首先要排除values是数组的可能性。

    接下来,您的函数isPlainObject 的返回类型定义为obj is object。这太通用了,并且会导致您的代码块“忘记”该对象具有索引签名。必须是obj is StringMap

    所以在实践中,你需要做两件事:

    1. 在您的第一个 if 语句中,检查值是否为数组
    2. 将您的 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`);
      }
    }
    

    【讨论】:

    • 我必须先检查数组,因为数组在技术上是对象?是这个原因吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 2018-06-29
    • 2016-07-23
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多