面试题答案
一键面试设计思路
- 共享DTO类型定义:在一个共享的TypeScript文件中定义DTO类型,确保前后端使用相同的类型定义。
- 前端类型安全:在React组件中使用这些类型定义来处理表单数据,利用类型推断简化类型声明。
- 后端类型安全:在Node.js和Express应用中使用相同的DTO类型定义进行数据验证和处理,通过联合类型处理可能的错误情况。
- 交叉类型:可以用于合并多个类型的属性,比如在后端验证成功后返回的对象可能会合并了原始DTO和一些附加信息。
关键代码示例
1. 共享DTO类型定义
在一个共享的types.ts
文件中定义DTO类型:
// types.ts
export interface UserDTO {
username: string;
email: string;
age: number;
}
2. 前端React部分
import React, { useState } from'react';
import { UserDTO } from './types';
const UserForm: React.FC = () => {
const [userData, setUserData] = useState<UserDTO>({
username: '',
email: '',
age: 0
});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
if (name === 'age') {
setUserData({...userData, [name]: parseInt(value) });
} else {
setUserData({...userData, [name]: value });
}
};
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// 这里可以将userData发送到后端
console.log('Submitting data:', userData);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" name="username" onChange={handleChange} placeholder="Username" />
<input type="email" name="email" onChange={handleChange} placeholder="Email" />
<input type="number" name="age" onChange={handleChange} placeholder="Age" />
<button type="submit">Submit</button>
</form>
);
};
export default UserForm;
3. 后端Node.js和Express部分
import express from 'express';
import { UserDTO } from './types';
const app = express();
app.use(express.json());
app.post('/submit', (req, res) => {
const userData: UserDTO | null = req.body;
if (!userData || typeof userData.username!=='string' || typeof userData.email!=='string' || typeof userData.age!== 'number') {
return res.status(400).json({ error: 'Invalid data' });
}
// 数据验证通过,进行处理
console.log('Received data:', userData);
res.json({ message: 'Data received successfully' });
});
const port = 3000;
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
在上述代码中,通过共享UserDTO
类型定义,前端在表单处理中确保输入的数据类型符合要求,后端在接收数据时进行类型验证,利用类型推断简化代码编写,同时通过联合类型处理可能的错误情况。如果需要合并类型,比如后端处理后返回的数据类型,可以使用交叉类型,例如:
// 假设后端处理后返回的数据类型
export interface ProcessedUserDTO extends UserDTO {
processedAt: string;
}
这样就可以在需要的地方使用ProcessedUserDTO
类型,它包含了UserDTO
的所有属性以及新的processedAt
属性。