【问题标题】:Typescript Discriminant property type not working with generic typesTypescript 判别属性类型不适用于泛型类型
【发布时间】:2023-02-11 01:10:00
【问题描述】:

我正在尝试创建一个模式并根据模式推断类型

但是,data的类型与我预期的不一样,它应该是{ love: string }而不是if循环内的{ love: string } | { eat: string }

const users = {
    //...
}

//Similar to zod's 'z.infer'
//This is an example type generated from 'users' schema
type Users = {
    henry: {
        data: {
            love: string;
        };
    };
    kyle: {
        data: {
            eat: string;
        };
    };
};

type UserMessage<U extends keyof Users = keyof Users> = {
    user: U
    data: Users[U]['data']
}

//example input (unknown type)
const test: unknown = { user: 'henry', data: { love: 'kyle'}}
const typed = test as UserMessage

if (typed.user === 'henry') {
    typed.data //Type: { love: string } | { eat: string }
}

有什么推荐的方法可以在 Typescript 中做这件事吗?

【问题讨论】:

  • 您的UserMessage&lt;keyof Users&gt; 类型不是受歧视的联盟;每个属性都是一个联合,所以 user 是键,data 是属性;没有什么可以防止不匹配。你可以把UserMessage改成分配的正确分布在联合上的对象类型,如in this playground link所示。那能满足你的需求吗?如果是这样,我可以写一个答案来解释;如果没有,我错过了什么?

标签: typescript


【解决方案1】:

UserMessage 中实际上没有可区分的联合,只是具有联合的 userdata 属性的对象类型。

要生成可区分的联合,您可以使用 distributive property of conditional types

type UserMessage<U extends keyof Users = keyof Users> = U extends U ?{
    user: U
    data: Users[U]['data']
}: never

Playground Link

或者您可以使用映射类型并从中获取值的联合:

type UserMessage<U extends keyof Users = keyof Users> = {
    [K in U]: {
        user: K
        data: Users[K]['data']
    }
}[U]

Playground Link

【讨论】:

    猜你喜欢
    • 2021-11-14
    • 2021-07-05
    • 1970-01-01
    • 2019-05-30
    • 2019-03-31
    • 2021-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多