Express.js-在请求对象内按主体进行转换

时间:2019-06-06 16:43:14

标签: javascript node.js typescript express

我为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"
}

TypeScript playground

1 个答案:

答案 0 :(得分:2)

  

那样的话,它将接口的非成员属性分配给我的变量。

如果您不希望这样做,则不能使用强制转换(它不是真正的强制转换,在TypeScript中称为 type assertion )。您必须创建一个新对象。

您可以通过解构来实现此目的,尽管您可以通过更快地(在参数列表中)使其变得不那么笨拙,并且不需要其类型断言,但TypeScript会看到您分配的是可以接受的:

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

根据类型信息自动执行此操作(无需键入titlebody)将需要TypeScript提供运行时类型信息,currently outside TypeScript's goals(尽管这通常是-要求的功能)。

当然,不必破坏结构。您可能有一个属性名称数组(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);
})