我想提取嵌套对象的键类型,并尝试如下所示。
type RecursiveRecord = {
[key in string]: string | RecursiveRecord;
};
type Keys<T extends RecursiveRecord, K = keyof T> = K extends string
? T[K] extends string
? K
: T[K] extends RecursiveRecord
? K | Keys<T[K]> // here I got error
: never
: never;
type Obj = {
a: {
c: 'aaaaaa';
d: 'aaaaaaaaaaa';
e: { f: 'q' };
};
b: 'dd';
};
export type A = Keys<Obj>; // want to get "a" | "b" | "c" | "d" | "e" | "f"但是在K | Keys<T[K]>上,我得到了以下类型错误。有什么干净的办法解决这个问题吗?
index.ts:9:16 - error TS2344: Type 'T[K]' does not satisfy the constraint 'RecursiveRecord'.
Type 'T[string]' is not assignable to type 'RecursiveRecord'.
Type 'string | RecursiveRecord' is not assignable to type 'RecursiveRecord'.
Type 'string' is not assignable to type 'RecursiveRecord'.发布于 2021-04-22 14:08:47
关于这个问题,在类型记录的GitHub回购中至少有一个悬而未决的问题:关于允许条件类型跟踪更复杂的检查类型(如T[K] )的建议,请参见微软/打字稿#25804。现在,一个只是被列为“等待更多的反馈”,所以如果我们想看到对它做了什么,我们可能应该给它一个和描述我们令人信服的用例。我不确定是否有一个更规范的GitHub问题,但就目前而言,这只是语言的方式。
当编译器忘记一些我们认为应该记住的约束时,我们可以做的就是“提醒它”。通常我的方法是:如果XXX类型应该受到YYY的约束,但编译器没有意识到它,我将XXX替换为Extract<XXX, YYY>,使用实用程序类型来“过滤”YYY的XXX。如果XXX确实可以分配给YYY,那么这个过滤器将是不操作的,但是现在编译器将认识到Extract<XXX, YYY>是可以分配给YYY的。
这就给了你这个:
type Keys<T extends RecursiveRecord, K = keyof T> =
K extends string ? (
T[K] extends string ? K :
T[K] extends RecursiveRecord ? K | Keys<Extract<T[K], RecursiveRecord>> :
never
) : never;它解决了错误。
当然,对于这个操作,我可能会写一些更类似的东西:
type NestedKeys<T> =
T extends object ? { [K in keyof T]-?: K | NestedKeys<T[K]> }[keyof T] : never;至少在您的例子中,结果是相同的:
type B = NestedKeys<Obj>
// type B = "a" | "b" | "c" | "d" | "e" | "f"https://stackoverflow.com/questions/67214581
复制相似问题