Почему Zod делает все поля моей схемы необязательными?

Я использую Zod в своем проекте API Express, TypeScript и Mongoose, и при попытке проверить мой пользовательский ввод по пользовательской схеме он возвращает конфликты типов:

        Argument of type '{ firstName?: string; lastName?: string; password?: string; passwordConfirmation?: string; email?: string; }' is not assignable to parameter of type 'UserInput'.
      Property 'email' is optional in type '{ firstName?: string; lastName?: string; password?: string; passwordConfirmation?: string; email?: string; }' but required in type 'UserInput'

Вот определение схемы:

      export const createUserSchema = object({
  body: object({
    firstName: string({
      required_error: 'First name is required',
    }),
    lastName: string({
      required_error: 'Last name is required',
    }).nonempty(),
    password: string({
      required_error: 'Password is required',
    })
      .nonempty()
      .min(6, 'Password too short - should be 6 chars minimum'),

    passwordConfirmation: string({
      required_error: 'Confirm password is required',
    }),
    email: string({
      required_error: 'Email is required',
    })
      .email('Not a valid email')
      .nonempty(),
  }).refine((data) => data.password === data.passwordConfirmation, {
    message: 'Passwords do not match',
    path: ['passwordConfirmation'],
  }),
});

export type CreateUserInput = Omit<TypeOf<typeof createUserSchema>, 'body.passwordConfirmation'>;


export interface UserInput {
  email: string;
  firstName: string;
  lastName: string;
  password: string;
}

Как сделать все эти поля схемы Zod необязательными, поскольку по умолчанию они становятся необязательными?

5 ответов

Это может быть вызвано неиспользованием strict: trueв параметрах компилятора TypeScript, как указано в разделе установки в файле README .

Следующий базовый файл tsconfig.json исправит это:

      {
    "compilerOptions": {
        "strict": true   
    }
}

Как отметил @pr0gramist в комментариях, принятым ответом должно быть добавление этого параметра в вашtsconfig.json:

      {
    "compilerOptions": {
        "strictNullChecks": true   
    }
}

В зависимости от конфигурации zod по умолчанию вам также может потребоваться добавить это в свои схемы:

      requiredField: z.string().nonempty()

Этот метод менее интрузивен, чем"strict": true, что добавляет дополнительные ограничения машинописного текста в вашу базу кода.

.nonempty() устарел. Просто используйте вместо этого .min(1)

Я предлагаю создать базовую версию, а затем расширить ее с помощью «подтверждения пароля» и относительного уточнения. Также важно «выводить» из zod в машинописный текст, чтобы сделать доступным линтинг машинописного текста.

      import { object, string, z } from 'zod';

export const userSchema = object({
  firstName: string({
    required_error: 'First name is required',
  }),
  lastName: string({
    required_error: 'Last name is required',
  }).nonempty(),
  password: string({
    required_error: 'Password is required',
  })
    .nonempty()
    .min(6, 'Password too short - should be 6 chars minimum'),
  email: string({
    required_error: 'Email is required',
  })
    .email('Not a valid email')
    .nonempty(),
});
type userSchema = z.infer<typeof userSchema>;

export const createUserSchema = object({
  body: userSchema
    .extend({
      passwordConfirmation: string({
        required_error: 'Confirm password is required',
      }),
    })
    .refine((data) => data.password === data.passwordConfirmation, {
      message: 'Passwords do not match',
      path: ['passwordConfirmation'],
    }),
});
type createUserSchema = z.infer<typeof createUserSchema>;

const us: userSchema = {
  email: '',
  firstName: '',
  lastName: '',
  password: '',
};

const cui: createUserSchema = {
  body: {
    email: '',
    firstName: '',
    lastName: '',
    password: '',
    passwordConfirmation: '',
  },
};

Вы все еще можете использовать универсальный тип Requiredчтобы пометить объект как требуется:

      export type X = Required<CreateUserInput>

Вы все еще можете сделать это с подобъектами вашей схемы, если у вас есть, например, параметры, тело и запрос:

      export type X = Required<CreateUserInput['body']>
Другие вопросы по тегам