Я делаю библиотеку проверки формы, когда пользователь хочет отправить форму, ему понадобятся типы, я застрял в этой части.

У меня есть следующий код

interface Validation {
  name: string
  message: string
  params?: Record<string, any>
  test: (value: any, params?: any) => boolean
}

class StringSchema {
  validations: Validation[] = []

  required(): this {
    this.validations.push({
      name: 'required',
      message: 'this field is required',
      test: (value: string) => {
        return value === '' ? false : true
      },
    })

    return this
  }

  email(): this {
    this.validations.push({
      name: 'email',
      message: 'enter valid email',
      test: (value: string) => true,
    })

    return this
  }
}

class NumberSchema {
  validations: Validation[] = []

  between(min: number, max: number) {
    type Params = { min: number; max: number }

    this.validations.push({
      name: 'between',
      params: { min, max },
      message: 'must be between {min} and {max}',
      test: (value: number, params: Params) => {
        return value >= params.min && value <= params.max
      },
    })

    return this
  }

  optional() {
    return this
  }
}

const schema = {
  string() {
    return new StringSchema()
  },
  number() {
    return new NumberSchema()
  },
}

// --------------------------

const form = {
  name: schema.string().required().email(),
  age: schema.number().between(18, 50),
}

вот TS Playground

Теперь, когда form определен, я хотел бы получить из него интерфейс, например:

type Fields = typeof form

Это возвращает мне это:

enter image description here

Но я бы хотел что-то вроде этого

enter image description here

Может кто-нибудь добиться мне такого результата? Я благодарю всех

да делает что-то подобное, yup.TypeOf<typeof form>

Я застрял на 100%, я не очень разбираюсь в TypeScript, но я бы хотел, чтобы он работал

Я благодарю всех

1
Yung Silva 20 Май 2021 в 02:28

1 ответ

Лучший ответ

Если вы используете класс маркера, например:

class Schema<T> {
  // This useless prop must be included to ensure T isn't thrown away
  // The exclamation mark asserts it is assigned (preventing non-assignment warnings)
  _!: T; 
}

И расширите из него элементы схемы:

class StringSchema extends Schema<string> {

Тогда вы можете написать тип для вывода вашего типа формы:

const form = {
  name: schema.string().required().email(),
  age: schema.number().between(18, 50).optional(),
}

type FormType<T> = {
  [P in keyof T]: T[P] extends Schema<infer TS> ? TS : never;
};

type Form = FormType<typeof form>

const test: Form = {
  name: 'Yung',
  age: 10
}

Детская площадка

Сделав еще один шаг, ваши функции проверки, вместо того, чтобы возвращать this, можно было бы переписать так, чтобы они вели себя неизменно, возвращая новую схему (с validations, скопированную в новую схему), которая несет измененный тип в своем класс маркера. Упражнение для читателя.

3
spender 20 Май 2021 в 00:14