【问题标题】:TypeScript type definition for an object property path [duplicate]对象属性路径的 TypeScript 类型定义
【发布时间】:2020-04-14 18:19:31
【问题描述】:

是否可以键入字符串数组,使该数组只能是给定对象中的有效属性路径?类型定义应该适用于所有深度嵌套的对象。

例子:

const object1 = {
    someProperty: true
};
const object2 = {
    nestedObject: object1,
    anotherProperty: 2
};

type PropertyPath<Type extends object> = [keyof Type, ...Array<string>]; // <-- this needs to be improved

// ----------------------------------------------------------------

let propertyPath1: PropertyPath<typeof object1>;

propertyPath1 = ["someProperty"]; // works
propertyPath1 = ["doesntExist"]; // should not work

let propertyPath2: PropertyPath<typeof object2>;

propertyPath2 = ["nestedObject", "someProperty"]; // works
propertyPath2 = ["nestedObject", "doesntExist"]; // should not work
propertyPath2 = ["doesntExist"]; // should not work

Link to TypeScript playground

【问题讨论】:

  • 我不太明白“应该适用于所有深层嵌套的对象。”,因为这似乎是不可能的。但是,您可以输入:type PropertyPath&lt;Type extends object&gt; = (keyof Type)[];

标签: typescript recursion reflection types jsonpointer


【解决方案1】:

可以使用箭头函数

const object1 = {
    someProperty: true
};
const object2 = {
    nestedObject: object1,
    anotherProperty: 2
};

type PropertyPath<Type extends object> = (x: Type) => any;

let propertyPath1: PropertyPath<typeof object1>;

propertyPath1 = (x) => x.someProperty; // works
propertyPath1 = (x) => x.doesntExist; // should not work

let propertyPath2: PropertyPath<typeof object2>;

propertyPath2 = (x) => x.nestedObject.someProperty; // works
propertyPath2 = (x) => x.nestedObject.doesntExist; // should not work
propertyPath2 = (x) => x.doesntExist; // should not work

Playground Link

【讨论】:

  • 谢谢,但这不是我想要的
【解决方案2】:

the answer to the question this duplicates 中,您可以使用递归Paths&lt;&gt;Leaves&lt;&gt; 类型别名,具体取决于您是否要支持从根开始并在树中任意位置结束的所有路径 (Paths&lt;&gt;) 或如果你只想支持从根开始到叶子结束的路径(Leaves&lt;&gt;):

type AllPathsObject2 = Paths<typeof object2>;
// type AllPathsObject2 = ["nestedObject"] | ["nestedObject", "someProperty"] | 
//  ["anotherProperty"]

type LeavesObject2 = Leaves<typeof object2>;
// type LeavesObject2 = ["nestedObject", "someProperty"] | ["anotherProperty"]

我假设它是Paths,但如果适合您的用例,您可以将其更改为Leaves。这是你得到的行为,它符合你的要求:

let propertyPath1: Paths<typeof object1>;
propertyPath1 = ["someProperty"]; // works
propertyPath1 = ["doesntExist"]; // error!
//               ~~~~~~~~~~~~~~

let propertyPath2: Paths<typeof object2>;
propertyPath2 = ["nestedObject", "someProperty"]; // works
propertyPath2 = ["nestedObject", "doesntExist"]; // error!
//                               ~~~~~~~~~~~~~
propertyPath2 = ["doesntExist"]; // error!
//               ~~~~~~~~~~~~~

好的,希望对您有所帮助;祝你好运!

Link to code

【讨论】:

  • 太棒了,谢谢! Paths 是我要找的。这是你永远不想在你的代码库中拥有的这种类型,你很高兴别人为你做了它:D
  • 这可能是我见过的最严重的 Typescript 巫术。不错!
  • 是否有更好的解决方案来使用数组中的相同数据访问密钥而不加入它们
  • @Shivam 我不明白这个问题,抱歉。
  • @jcalz 我的意思不是在数组 ["someProp"] 中访问或定义它们,然后使用数组 [0] 访问对象键值,我们如何才能将路径用作字符串,例如 "一些道具”?
猜你喜欢
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 2020-07-31
  • 2022-01-17
  • 2019-04-05
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多