4

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

例子:

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

链接到 TypeScript 游乐场

4

2 回答 2

6

这个重复的问题的答案中,您可以使用递归Paths<>Leaves<>类型别名,具体取决于您是否要支持从根开始并在树中任何位置结束的所有路径(Paths<>),或者您是否只想支持从树的根开始,到树的叶子结束 ( Leaves<>):

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!
//               ~~~~~~~~~~~~~

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

链接到代码

于 2019-12-23T16:55:29.033 回答
-4

可以使用箭头函数

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

游乐场链接

于 2019-12-23T13:45:01.597 回答