【问题标题】:Typescript: Merging types (vs intersecting them)打字稿:合并类型(与相交)
【发布时间】:2020-03-16 18:57:41
【问题描述】:

考虑以下

type MergeFn = <K1 extends string, V1, K2 extends string, V2>(
   k1: K1, v1: V1,
   k2: K2, v2: V2
) => ???

let mergeFn: MergeFn // implementation not relevant to question

??? 需要填写什么,以便

mergeFn(
  "hello", 1,
  "typescript", 2
)

类型为{ hello: number, typescript: number }

我试过了

??? = { [k in K1]: V1 } &amp; { [k in K2]: V2 }

但结果会是

{ hello: number } &amp; { typescript: number }.

(按照提议的here 应用type Id&lt;T&gt; = { [k in keyof T]: T[k] } 也无济于事。)

Example in the typescript playground

【问题讨论】:

    标签: typescript generics typescript-typings


    【解决方案1】:

    您可以这样做的一种方法是使用单个条件映射类型而不是交集:

    type MergeFn = <K1 extends string, V1, K2 extends string, V2>(
        k1: K1, v1: V1,
        k2: K2, v2: V2
    ) => { [K in K1 | K2]: K extends K1 ? V1 : V2}
    

    产生

    const test = mergeFn(
        "hi", 4,
        "there", 4
    )
    /* const test: {
        hi: number;
        there: number;
    } */
    

    当您说Id&lt;T&gt;“没有帮助”时,我假设您的意思是编译器决定向您显示一个类型别名,例如Id&lt;A &amp; B&gt;,而不是为您扩展它。我发现在这种情况下,处理它的方法是通过一个中间条件类型,像这样:

    type Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never
    

    如果我在您的原始代码上使用它:

    type MergeFn = <K1 extends string, V1, K2 extends string, V2>(
        k1: K1, v1: V1,
        k2: K2, v2: V2
    ) => Expand<Record<K1, V1> & Record<K2, V2>>
    

    我得到相同的输出:

    const test = mergeFn(
        "hi", 4,
        "there", 4
    )
    /* const test: {
        hi: number;
        there: number;
    } */
    

    所以任何一种方式都适合你。


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

    Link to code

    【讨论】:

    • 这正是我所说的“没用”。如果我只关心结果类型,我也可以使用 A &amp; B,但我正在寻找漂亮的编译器输出。
    猜你喜欢
    • 1970-01-01
    • 2018-09-15
    • 2022-01-13
    • 2020-08-05
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多