简体   繁体   English

在TypeScript接口密钥迭代中使用条件类型

[英]use conditional type in typescript interface key iteration

Hi have 2 interfaces and a type 嗨,有2个接口和一个类型

interface A { k1: string k2: string }

interface B { k3: string k4: A }

type Error = { key:string, value:string}

I have developed a declaration that creates an interface with all the keys of a given interface and the type = Error[] 我已经开发了一个声明,该声明使用给定接口的所有键和类型= Error []创建一个接口

type AutoErrors<P> = { [K in keyof P]-?: Error[] }

That works well since AutoErrors<A> gives { k1: Error[] k2: Error[] } 由于AutoErrors<A>给出{ k1: Error[] k2: Error[] }效果很好

But now I would like it to be recursive, ie , if the parameter type key is not of type string I would like its type to be AutoErrors<T> 但是现在我希望它是递归的,即,如果参数类型键不是字符串类型,我希望它的类型是AutoErrors<T>

For example AutoErrors<B> should be { k3: Error[], k4: AutoErrors<A> } 例如, AutoErrors<B>应该为{ k3: Error[], k4: AutoErrors<A> }

I have tried 我努力了

type AutoErrors<X> = { [K in keyof X]-?: X[K] extends string ? Error[] : AutoErrors<X[K]> } type AutoErrors<X> = { [K in keyof X]-?: X[K] extends string ? Error[] : AutoErrors<X[K]> } but it is not working well , as if the test X[K] extends string is not well interpreted type AutoErrors<X> = { [K in keyof X]-?: X[K] extends string ? Error[] : AutoErrors<X[K]> }但是它不能很好地工作,好像测试X [K]扩展字符串不能很好地解释

You can use an approach similar to the one for DeepReadOnly 您可以使用与DeepReadOnly类似的方法

export type primitive = string | number | boolean | undefined | null
export type DeepError<T> = 
    T extends (infer U)[] ? Array<DeepErrorObject<U>> :
    T extends primitive ? Error[] : DeepErrorObject<T>;

export type DeepErrorObject<T> = {
readonly [P in keyof T]: DeepError<T[P]>
}
// sample usage
interface A {
    k1: string
    k2: string
} 
interface B {
    k3: string
    k4: A
    k4Arr: B[]
}
type Error = { 
    key:string, 
    message:string
}

type ErrorA = DeepError<B>
let d: ErrorA;
d.k4Arr[0].k3; // Error[]

The code as posted in your question works in the Playground , so I suspected that something else was going on. 您的问题中张贴的代码在Playground中有效 ,因此我怀疑还有其他情况。 As it turns out, the issue had to do with optional properties, such as 事实证明,此问题与可选属性有关,例如

type UhOh = AutoErrors<{ a?: string }>; // becomes {a: string}, not good

The original AutoErrors<> definition didn't work in that case, because string | undefined 原始的AutoErrors<>定义在这种情况下不起作用,因为string | undefined string | undefined does not extend string . string | undefined不扩展string The fix for that, as you know, is to check for string | undefined 如您所知,解决此问题的方法是检查string | undefined string | undefined instead of just string : string | undefined而不只是string

type AutoErrors<X> = {
  [K in keyof X]-?: X[K] extends string | undefined ?
  Error[] : AutoErrors<X[K]>
}

which works: 哪个工作:

type Okay = AutoErrors<{ a?: string }>; // becomes {a: Error[]}, as expected

Glad you found out what was going on. 很高兴您发现发生了什么事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM