【问题标题】:use conditional type in typescript interface key iteration在打字稿界面键迭代中使用条件类型
【发布时间】:2018-12-04 04:26:29
【问题描述】:

你好有2个接口和一个类型

interface A {
    k1: string
    k2: string
}

interface B {
    k3: string
    k4: A
}

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

我开发了一个声明,它使用给定接口的所有键和type = Error[] 创建一个接口

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

这很好用,因为AutoErrors&lt;A&gt; 给出了

{
  k1: Error[]
  k2: Error[]
}

但现在我希望它是递归的,即如果参数类型键不是字符串类型,我希望它的类型是AutoErrors&lt;T&gt;

例如AutoErrors&lt;B&gt;应该是

{
  k3: Error[],
  k4: AutoErrors<A>
}

我试过了

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

但效果不好,好像测试 X[K] extends string 没有得到很好的解释

【问题讨论】:

  • “我试过了,但效果不好”……具体来说,你试过什么?
  • 对不起,我修正了错字
  • 你使用的是什么版本的 TypeScript?它有什么不好的地方?
  • 您上面的代码在the playground 中工作,所以正在发生其他事情。
  • 你是绝对正确的@jcalz,但我在 VSCOde 编辑器中看到一个错误,因为我正在尝试使用仅包含可选键的界面。为此,我添加到状态 X[K] 扩展字符串 |不明确的。你绝对应该得到奖励,因为你的陈述帮助我找出问题所在,发布最终版本,我会投票给你。

标签: typescript


【解决方案1】:

您的问题works in the Playground 中发布的代码,所以我怀疑发生了其他事情。事实证明,这个问题与可选属性有关,例如

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

原来的AutoErrors&lt;&gt; 定义在这种情况下不起作用,因为string | undefined 没有扩展string。如您所知,解决方法是检查string | undefined 而不仅仅是string

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

哪个有效:

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

很高兴你知道发生了什么。

【讨论】:

    【解决方案2】:

    您可以使用类似于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[]
    

    【讨论】:

    • OP 代码应该可以用于所述目的,所以还有其他事情要做。
    • @jcalz 嗯..你是对的,我没有看到更新,他的代码应该可以正常工作..
    猜你喜欢
    • 2022-06-23
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 2021-12-06
    • 2019-05-03
    • 2020-08-31
    • 2021-12-04
    • 2022-01-05
    相关资源
    最近更新 更多