是的带有 TypeScript 联合类型的 ObjectSchema

问题描述 投票:0回答:1

假设我有两种类型,

BasicUser
AdminUser
,它们合并为一种类型
User

interface UserBase {
  name: string
  authenticationType: AuthenticationType;
}

interface BasicUser extends UserBase {
  authenticationType: 'basicUser';
  privileges: string;
}

interface AdminUser extends UserBase {
  authenticationType: 'adminUser';
}

export type User = BasicUser | AdminUser;

我正在尝试构建一个模式,可以验证

User
类型,无论它是构造为
AdminUser
还是
BasicUser

import * as yup from 'yup';
import { AuthenticationType, User } from './types';

const bobAdmin: User = {
  name: 'Bob',
  authenticationType: 'adminUser',
}

const sallyBasicUser: User = {
  name: 'Sally',
  authenticationType: 'basicUser',
  privileges: 'read'
}

// Schema validation fails typecheck
const userSchema: yup.ObjectSchema<User> = yup.object({
  name: yup.string().required(),
  authenticationType: yup.string().oneOf<AuthenticationType>(['basicUser', 'adminUser']).defined().required(),
  privileges: yup.string().when('authenticationType', ([authenticationType], schema) => {
    if(authenticationType === 'basicUser') {
      return schema.required();
    }
    return schema;
  })
});

验证确实有效,但 TypeScript 抱怨架构不满足

User
类型。

Image of typescript error

我尝试将模式分解为两个不同的模式并使用

mixed().oneOf([])
,但这也不起作用。

有没有人可以提供任何解决方法或提示?谢谢你。

https://stackblitz.com/edit/vitejs-vite-fszugq?file=src%2Fmain.ts

typescript yup
1个回答
0
投票

显然,是的,不支持该功能。我的解决方法是将架构的失败部分转换为

any
...不理想。

Zod 使用 歧视性工会 很好地处理了这个案例。

const userSchema = z.discriminatedUnion('authenticationType', [
    z.object({ authenticationType: z.literal('adminUser') }).merge(baseUserSchema),
    z.object({ authenticationType: z.literal('basicUser'), privileges: z.string() }).merge(baseUserSchema),
]) satisfies z.ZodType<User>;  // Gives you schema typing against User type

https://stackblitz.com/edit/vitejs-vite-bcbhz1?file=src%2Fmain.ts

© www.soinside.com 2019 - 2024. All rights reserved.