简体   繁体   English

TypeScript:从接口动态创建联合类型

[英]TypeScript: Create union type dynamicaly from interface

I want to generate a type Response我想生成一个类型Response

type Response = 
{
    code: 200
    body: {
        msg: string
    }
} | {
    code: 400
    body: {
        errorCode: number
    }
}

from Foo (simplified version of the type generated by .来自Foo.

interface Foo {
    200: {
        msg: string
    }
    400: {
        errorCode: number
    }
}

I tried below but it doesn't work.我在下面尝试过,但它不起作用。

type Response = {
    code: keyof Foo // 200 | 400
    body: Foo[keyof Foo] // {msg: string} | {errorCode: number}
}


const res: Response = {
    code: 200,
    body: {
        errorCode: 1 // not get an error
    }
}

Can someone help me?有人能帮我吗?

Right now you are mixing all possible code types with all possible body types.现在,您正在将所有可能的code类型与所有可能的body类型混合在一起。 You need to use a mapped type instead to explicitly iterate over each key K of Foo and make each element a function of K the key, and Foo[K] the value.您需要使用映射类型来显式迭代Foo每个K并使每个元素成为K的 function 键和Foo[K]值。 This produces a new object type like {200: {code: 200, ...}, 400: {code: 400, ...} which you want to look up to get the union of its properties:这会产生一个新的 object 类型,例如{200: {code: 200, ...}, 400: {code: 400, ...}您要查找它以获取其属性的并集:

type Resp = { [K in keyof Foo]: { code: K, body: Foo[K] } }[keyof Foo];

/* type Resp = {
    code: 200;
    body: {
        msg: string;
    };
} | {
    code: 400;
    body: {
        errorCode: number;
    };
} */

(I renamed it Resp because there's already a Response in global scope I don't want to collide with). (我将其重命名为Resp ,因为我不想与之冲突的全局 scope 中已经有一个Response )。

Then you get the desired error when using the wrong body with a given code :然后,当使用给定code的错误body时,您会得到所需的错误:

const res: Resp = {
    code: 200,
    body: {
        errorCode: 1 // error!
    //  ~~~~~~~~~~~~
    // Type '{ errorCode: number; }' is not assignable to type '{ msg: string; }'.
    }
}

Playground link to code Playground 代码链接

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

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