Express.js - приведение интерфейса по телу внутри объекта запроса - PullRequest
2 голосов
/ 06 июня 2019

Я написал аналогичное основание для структуры ASP.NET MVC и выпустил на моем github ( express-mvc ). Все хорошо, но я не могу привести body внутрь объекта request, чтобы он подходил для любого интерфейса

Это именно то, что я хочу:

export default interface Post {
    title: string
    body: string
}
import Post from '@models/user'

router.post("/post", (req: Request, res: Response) => {
    const Model: Post = req.body
})

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

const Model;
Model = req.body

Когда это так, он присваивает неинтерфейсное свойство интерфейса моей переменной.

Короче говоря, я хочу известные свойства интерфейса в переменной Model.

Я использую деструктурирование, чтобы временно решить проблему в этом проекте

import Post from '@models/user'

router.post("/post", (req: Request, res: Response) => {
    const { title, body }: Post = req.body

    const Model: Post = <Post>{
        title,
        body
    };
})

Есть ли у вас какие-либо предложения


Решить проблему с классами

function castByBody<Model>(source: {}, modelProperties: any[]): Partial<Model> {
    const post: Partial<Model> = {};
    for (const key of modelProperties) {
        post[key] = source[key];
    }
    return post;
}

class User {
  public first_name: string = null
  public username: string = null
  public email: string = null
  public password: string = null
  public age: number = null
}

let user = new User() // create new instance
let userProperties: any[] = Object.getOwnPropertyNames(user) // get all properties from instance

const reqBody = { 
  first_name: "afulsamet",
  username: "aful",
  email: "afulsamet@gmail.com",
  password: "333222233",
  title: "member", 
  age: 18 
} // user instance does not have title property

const model: Partial<User> = castByBody<User>(reqBody, userProperties);

console.log(model)

Вывод будет как в консоли

{
  age: 18
  email: "afulsamet@gmail.com"
  first_name: "afulsamet"
  password: "333222233"
  username: "aful"
}

Детская игровая площадка

1 Ответ

2 голосов
/ 06 июня 2019

Когда это так, он присваивает неинтерфейсное свойство интерфейса моей переменной.

Если вы этого не хотите, то вы не можете использовать приведение (это недействительно приведение, в TypeScript это называется утверждение типа ).Вам действительно нужно создать новый объект.

Вы можете сделать это с помощью деструктурирования, как вы это делаете, хотя вы можете заставить его чувствовать себя немного неуклюже, сделав это раньше (в списке параметров), и вы неДля этого не требуется утверждение типа, TypeScript увидит, что назначаемое вами значение приемлемо:

router.post("/post", ({body: { title, body }}, res: Response) => {
    const Model: Post = {
        title,
        body
    };
})

Выполнение этого автоматически (без необходимости ввода title и body) на основе информации о типепотребовалось бы, чтобы TypeScript предоставил информацию о типе среды выполнения, которая в настоящее время не соответствует целям TypeScript (хотя это часто запрашиваемая функция).

Конечно, это не должно быть деструктуризацией.Вы можете иметь массив имен ваших свойств (что не даст вам TypeScript), возможно, он будет определен рядом с типом, и вместо этого использовать его:

const PostKeys = ["title", "body"];

затем

router.post("/post", ({body}, res: Response) => {
    const Model: {} as Post;
    for (const key of PostKeys) {
        Model[key] = body[key];
    }
})

возможно, даже сделать его функцией многократного использования

function createPost(source: any): Post {
    const post: {} as Post;
    for (const key of PostKeys) {
        post[key] = source[key];
    }
    return post;
}

затем

router.post("/post", ({body}, res: Response) => {
    const Model: createPost(body);
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...