如何在Typescript中键入深度对象破坏结构?

时间:2018-12-21 20:26:30

标签: typescript typing destructuring google-chrome-storage

我正在尝试在Typescript中键入一个深度对象分解,我搜索了一大堆,但没有找到能完全回答我问题的内容,所以我想问一下。

我班上有类似 的东西:

public Example(
  key1: string,
  key2: string,
  val: string,
  callback: (list: string[]) => void
): void
{
  chrome.storage.sync.get(
    ({
      [key1]: list1,
      [key2]: list2
    }) => {
      list1.includes(val)
        ? callback(list1.filter(i => i !== val))
        : callback(list2)
    }
  );
}

我还没有找到键入list1list2(如string[]的方法,它们被设置为any的方法,在尝试使用数组函数。我已经找到了一些示例,该示例说明了如果 key 是已知的({ key }: { key: string[] })如何键入,但我的情况并非如此。由于LHS是非静态的,因此我也无法创建Type。

我的示例有所更改,但包含了解决我的问题所需的一切。

如果需要的话,chrome.d.ts我说:

/**
 * Gets one or more items from storage.
 * @param callback Callback with storage items, or on failure (in which case runtime.lastError will be set).
 * Parameter items: Object with items in their key-value mappings.
 */
get(callback: (items: { [key: string]: any }) => void): void;

我敢肯定这可能真的很简单,我什么都没发现。话虽这么说,这个问题可能使其他人将来更容易找到,因此如果解决,它将是双赢的。

感谢所有帮助。


编辑:我想我也在寻找返回的不是 just string[]的情况。如果您有一堆都是不同类型的数据怎么办?

2 个答案:

答案 0 :(得分:1)

因此您将获得类型any,因为get函数具有这样的功能。

因此,您可以这样做:

type MyGet = (callback: (items: {[key: string]: string[]}) => void) => void

// inside the Example method
(chrome.storage.sync.get as MyGet)(
          ({
            [key1]: list1,
            [key2]: list2
          }) => {
            list1.includes(val)
              ? callback(list1.filter(i => i != val))
              : callback(list2)
          }
        );

在可能遇到其他类型的情况下,另一种更好的方法是使用类型保护:

chrome.storage.sync.get(
          ({
            [key1]: list1,
            [key2]: list2
          }) => {

            if(Array.isArray(list1)) {
              list1.includes(val)
                ? callback(list1.filter(i => i != val))
                : callback(list2)
            }
          }
        );

就类型安全而言,这是可以的,因为将类型any缩小为string[]应该被认为是可以的。

答案 1 :(得分:1)

使用declaration merging来更正第三方类型:

chrome.d.ts

import {} from 'chrome';

declare namespace chrome.storage {
  export interface StorageArea {
    get(callback: (items: { [key: string]: string[] }) => void): void;
  }
}

如果您想知道,将文件顶部的空白import语句要求将其视为模块增强而不是其定义。

最好的事情是什么?如果您对此处的string[]不满意,则可以通过其他方式对其进行扩充。您还可以将get设为通用。