如何捕获嵌套属性的类型参数并将其映射到其他内容

时间:2018-04-09 20:00:20

标签: typescript typescript2.8 conditional-types

我真的不知道如何提出这个问题所以我认为最好的方法是举例说明我要做的事情。让我们说我有以下对象:

const obj = {
  one: 'some string',
  two: new Set<string>(),
};

现在我想编写一个接收该对象的函数,并将Set转换为相同类型的Array

这里是无类型的javascript实现:

&#13;
&#13;
const obj = {
  one: 'some string',
  two: new Set().add('one').add('two'),
};

function convertToArrays(objWithSets) {
  return Object.entries(objWithSets).reduce((objectWithArrays, [key, value]) => {
    if (value instanceof Set) {
      objectWithArrays[key] = Array.from(value);
    } else {
      objectWithArrays[key] = value;
    }
    return objectWithArrays;
  }, {});
}


console.log('converted', convertToArrays(obj));
&#13;
&#13;
&#13;

如何正确输入上述功能?要澄清:它可以包含任何对象(不仅仅是一个,两个示例),如果它看到Set<T>,它会转换到Array<T>

我知道它需要捕获内部Set的类型(在这种情况下为string)并有条件地将该类型映射到Array<string>

谢谢!

1 个答案:

答案 0 :(得分:1)

您可以使用映射类型和条件类型的混合来执行此操作:

function convertToArrays<T extends { one: string, two: Set<any> }>(objWithSets: T):
    T extends { one: string, two: Set<infer U> }
        ? { one: string, two: Array<U> }
        : never {
  /* ... */
}

// typeof x === { one: string, two: number[] }
const x = convertToArrays({ one: "hello", two: new Set([1, 2, 3]) })

编辑:原创,过于具体的答案如下:

我们走了,基本上就像你描述的那样:

Set<any>

我们允许它最初只是never作为打字机,然后使用条件推断实际类型。匹配失败时条件会缩小到TypeError: $ is not a function ,这应该没问题,因为初始检查理论上保证条件总是会评估为真。