Typescript类型对象嵌套路径字符串

时间:2019-12-13 08:16:29

标签: typescript

我具有以下decode函数:

get

如何根据传递的参数动态键入结果?

1 个答案:

答案 0 :(得分:1)

非常有趣的情况。为了也从嵌套对象中收集所有键,我们需要进行递归,幸运的是,TS中提供了递归类型。但是,如果这样做,我们还会遇到其他问题,并且-Type instantiation is excessively deep and possibly infinite就这种确切情况而言,我们无法说出对象的深度,请检查此问题以了解我在说什么-issue

为了执行我们的聚会,我们需要在此处设置递归限制。我将限制设为5,您可以通过重复模式来扩展它。

首先输入类型:

type Level = 0 | 1 | 2 | 3 | 4 | 5 | 'max'; // this solves the infinite loop error issue
type NextLevel<Level> =
    Level extends 0 ? 1
    : Level extends 1 ? 2
    : Level extends 2 ? 3
    : Level extends 3 ? 4
    : Level extends 4 ? 5
    : 'max'; // this type enables iterating from 0 to 5, with the end as 'max'

type NestedKeyof<T, L extends Level = 0> = L extends 'max' ? never : {
    [K in keyof T]: T[K] extends object ? K | NestedKeyof<T[K], NextLevel<L>> : K
}[keyof T]

NestedKeyof类型是mapped type,它会收集映射中的所有键,但是如果键中的值是一个对象,则它将也为此对象执行收集。重要思想是K | NestedKeyof<T[K], NextLevel<L>>,因此我们递归传递对象T[K],然后通过NextLevel<L>迭代该级别。迭代以max类型结束,在类型的开头-L extends 'max' ? never可见。

该类型的简单测试显示正确的结果:

type NestedType = NestedKeyof<{ a: { b: 'hey', c: { d: 'elo' } } }>; // a | b | c | d

现在如何在您的函数中使用它:


function get<T, P extends NestedKeyof<T>>(obj: T, props: P[] | keyof T): any {
  const toArray = coereceArray(props);
  return obj && toArray.reduce(
    (result, prop) => result == null ? undefined : result[prop] as any,
    obj
  );
}

const result = get({ a: { b: 'hey' } }, ['a', 'b']); // correct
const result2 = get({ a: { b: 'hey' } }, 'a');  // correct
const result3 = get({ a: { b: 'hey' } }, ['a', 'b', 'c']); // error as expected

NestedKeyof类型有局限性,因为我为最多5个级别的嵌套对象创建了LevelNextLevel。例如这样的类型:

type NestedTypeAboveMax = NestedKeyof
<{ a: { b: 'hey', c: { d: 'elo', e: { f: { g: { h: {i: 'test'}} } } } } }>;

由于密钥i超出限制,因此不会使用。但是,如果将使用此类嵌套结构,则可以扩展LevelNextLevel使其具有更多级别。