代码之家  ›  专栏  ›  技术社区  ›  mpen

TS7017包含任何类型+类型推理

  •  1
  • mpen  · 技术社区  · 8 年前

    这是一个错误的浓缩片段:

    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)
        );
    }
    

    所以我认为 ISP对象 检查将排除 any[] 类型,从而 values 必须推断为 梯形图 但这似乎不是正在发生的事情。

    即使我做 ISP对象 返回 obj is StringMap ,typescript仍在抱怨。

    怎么会?我有没有办法不用打字就能把这一切都做好?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Stefano Dalpiaz    8 年前

    从技术上讲,数组仍然符合类型 {[key: string]: any} . 您可以通过执行以下操作来验证这一点 const test: StringMap = []; . typescript编译器不会抱怨。所以你首先必须排除 values 是一个数组。

    接下来,你的功能 isPlainObject 返回类型定义为 obj is object . 这太通用了,会导致代码块“忘记”对象有索引签名。它需要 obj is StringMap .

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

    1. 在你的第一 if 语句,检查值是否为数组
    2. 改变你 ISP对象 返回类型声明到 对象是字符串映射

    基本上看起来是这样的:

    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`);
      }
    }
    
    推荐文章