我正在用节点js和打字稿编写一个REST API,对于创建用户,我的api收到json帖子:
import {Request, Response, Router} from "express";
import {User} from '../../../models/user.model';
import {createUser} from '../../../factories/user.factory';
export default [
{
path: "/api/v1/user/create",
method: "post",
handler: [
async (req: Request, res: Response) => {
createUser(new User(req.body.user));
res.status(200).send(req.body);
}
]
}
];
例如,我发送:
{
"user": {
"email": "test@gmail.com",
"password": "12345678",
"firstName": "Jérémy"
}
}
我想用对象req.body.user创建一个对象“ User”:
import {Timestamp} from './timestamp.model';
export class User {
id: bigint | undefined;
email: string | undefined;
password: string | undefined;
firstName: string | undefined;
lastName: string | undefined;
pseudo: string | undefined;
birthDate: Timestamp | undefined;
lastEditDate: Timestamp | undefined;
creationDate: Timestamp | undefined;
googleAuthToken: string | undefined;
language: string | undefined;
profileAvatarUrl: string | undefined;
profileBannerUrl: string | undefined;
primaryLightColor: string | undefined;
secondaryLightColor: string | undefined;
primaryDarkColor: string | undefined;
secondaryDarkColor: string | undefined;
constructor(array: object) {
console.log(array);
// @ts-ignore
console.log(array.gg);
// @ts-ignore
this.id = array.id;
// @ts-ignore
this.email = array.email;
// @ts-ignore
this.password = array.password;
// @ts-ignore
this.firstName = array.firstName;
// @ts-ignore
this.lastName = array.lastName;
// @ts-ignore
this.pseudo = array.pseudo;
// @ts-ignore
this.birthDate = array.birthDate;
// @ts-ignore
this.lastEditDate = array.lastEditDate;
// @ts-ignore
this.creationDate = array.creationDate;
// @ts-ignore
this.googleAuthToken = array.googleAuthToken;
// @ts-ignore
this.language = array.language;
// @ts-ignore
this.profileAvatarUrl = array.profileAvatarUrl;
// @ts-ignore
this.profileBannerUrl = array.profileBannerUrl;
// @ts-ignore
this.primaryLightColor = array.primaryLightColor;
// @ts-ignore
this.secondaryLightColor = array.secondaryLightColor;
// @ts-ignore
this.primaryDarkColor = array.primaryDarkColor;
// @ts-ignore
this.secondaryDarkColor = array.secondaryDarkColor;
// @ts-ignore
}
toMap() {
return {
"id": this.id,
"email": this.email,
"firstName": this.firstName,
"lastName": this.lastName,
"pseudo": this.pseudo,
"profileAvatarUrl": this.profileAvatarUrl,
"birthDate": this.birthDate,
"lastEditDate": this.lastEditDate,
"creationDate": this.creationDate,
"language": this.language,
"googleAuthToken": this.googleAuthToken,
"profileBannerUrl": this.profileBannerUrl,
"primaryLightColor": this.primaryLightColor,
"secondaryLightColor": this.secondaryLightColor,
"primaryDarkColor": this.primaryDarkColor,
"secondaryDarkColor": this.secondaryDarkColor,
}
}
}
我把所有这些“ // @ ts-ignore”放进去,因为如果没有,我就遇到了这个错误:
src / models / user.model.ts(27,25):错误TS2339:属性“ id”没有 存在于“对象”类型上。 src / models / user.model.ts(28,32):错误TS2339: 属性“电子邮件”在类型“对象”上不存在。 src / models / user.model.ts(29,35):错误TS2339:属性“密码” 类型'object'上不存在。 src / models / user.model.ts(30,36): 错误TS2339:类型“对象”上不存在属性“名字”。 src / models / user.model.ts(31,35):错误TS2339:属性“ lastName” 类型'object'上不存在。
我的问题是:如何正确地使班级用户不必将所有这些“ // @ ts-ignore”放?
先谢谢您。 杰里米。
答案 0 :(得分:1)
我有一个不同的建议,我在打字稿中发现很好,并开始大量使用它。无需为您的用户创建类,您可以将其定义为接口。
^
然后简单地做:
export interface User {
email: string,
password: string,
firstName: string,
lastName: string,
// etc
}
只要将它们用于创建没有业务逻辑的域模型对象,键入它们的速度就会更快,更干净。
编辑:
如果您需要坚持上课,然后尝试使用 any 类型。
const user = req.body.user as User;
答案 1 :(得分:1)
我特别喜欢Dan的解决方案,既干净又快速。但是,如果他需要ToMap函数,可以考虑使用https://lodash.com/是一个非常方便的库,可以帮助处理数组,对象映射和深度克隆。
致谢
PD:您也可以使用索引器secondaryDarkColor =array.['secondaryDarkColor']
答案 2 :(得分:0)
有些事情可能需要清除,使解决方案变得模糊。
第一件事是您的toMap
方法是不必要的,因为ES6类是template for creating an object,所以用{{1}创建类的实例}关键字为您提供了一个对象,即使new
方法符合类型,它实际上也不会返回toMap
对象。如果您想返回User
,则需要将签名修改为:
User
这会通知编译器您打算返回toMap(): User { ... }
,否则,编译器只会看到该对象并将其推断为具有您定义的属性的具体对象。
此外,您的构造函数具有以下签名:
User
例如,调用变量constructor(array: object) { ... }
势必会引起混乱,对于读取代码的人,他们会假定他们正在使用数组,但是您将其键入为array
。
就类型错误而言,您之所以得到它们,是因为TypeScript的object
是因为它代表non-primitive type,实际上根本没有任何属性,因此当您尝试访问一个类型错误时,编译器无法访问它。
使用您当前的代码,您可以将object
替换为object
,并且很可能会进行编译,但是我认为您不希望这样做。
有一种更简洁的方法可以完成您要执行的操作,您实际上可以通过在构造函数中进行设置来定义属性及其类型,如下所示:
any
还请注意,您可以使用问号表示输入是可选的。
如果要接受json对象作为输入,而不是将所有内容都放入构造函数中,则可以始终在类上定义一个静态方法,该方法接受class User {
constructor(
public id?: string, // or private
public email?: string
) {}
}
const user = new User("abc123", "this@example.com")
console.log(user)
# >>> User: { "id": "abc123", "email": "this@example.com" }
作为输入并返回该类的实例
例如,请参见fiddle。