如何解决我的 Next.js 路由报告的 Typescript 错误?


import type { NextApiRequest, NextApiResponse } from "next";
import db from "../../app/libs/dbConn";
interface DataProps {
auth: [
{
name?: string;
email?: string;
passwordHash?: string;
}
];
status: number;
message: string;
}
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<DataProps>
) {
if (req.method === "POST") {
const data = {
name: "Gary",
email: `gary@${Math.floor(Math.random() * 9999999)}.subdomain.com`,
passwordHash: "-",
};
const user = await db.user.create({ data });
return res
.status(200)
.json({ auth: [data], status: 201, message: "created user" });
}
if (req.method === "GET") {
const allUsers = await db.user.findMany();
const users = allUsers.map((user) => {
return {
name: user.name || "",
email: user.email || "",
passwordHash: "" || "",
};
});
return res
.status(200)
.json({ auth: users, status: 200, message: "success" });
}
return res.status(404).json({
auth: [{}],
status: 405,
message: "http verb not supported",
});
}

在上面"GET"节,Typescript报告"auth&;因为有一个错误。错误是——类型'{名称:字符串;电子邮件:字符串;passwordHash:字符串;}[]'不能赋值给类型'[{name?: string |未定义;电子邮件?: string |未定义;passwordHash吗?: string |未定义;}]"。目标需要1个元素,但源可能更少。用户。ts(6,3):期望的类型来自属性'auth',它在类型'DataProps'上声明

我不明白我做错了什么。一切看起来都很好,如果我忽略Typescript错误,它就会像设计的那样工作。

我错过了一些我无法解决的问题。

您已经将auth声明为[ { name?: string; email?: string; passwordHash?: string; }]-换句话说,它是一个仅包含一个{ name?: string; email?: string; passwordHash?: string; }元素的单元素元组。但是代码期望的是{ name?: string; email?: string; passwordHash?: string; }[]——换句话说,是一个包含任意数量的{ name?: string; email?: string; passwordHash?: string; }元素的数组。因此,将DataProps.auth更改为{ name?: string; email?: string; passwordHash?: string; }[],您的代码应该可以工作。

更多信息,参见TypeScript手册中关于数组和元组的讨论。

更广泛地说,有几种方法可以用来声明类型:
  • 1-tuple ([{ name?: string; email?: string; passwordHash?: string; }])意味着它总是包含一个元素。这是一个奇怪的选择(如果我只有一件物品,我会直接返回{ name?: string; email?: string; passwordHash?: string }),但也许你的设计对它有特定的需求。
  • 一个数组({ name?: string; email?: string; passwordHash?: string }[])可以有0、1或无限项。
  • 如果你想在一个真实的用户对象上需要所有的属性,但是返回一个空对象来指示错误,你会使用一个联合类型(({ name: string; email: string; passwordHash: string } | Record<string, never>)[])。(Record<string, never>的解释见这里)
  • 个人而言,而不是返回一个空对象,我会使整个auth属性可选:
    interface User {
    name: string;
    email: string;
    passwordHash: string;
    }
    interface DataProps {
    auth?: User[];
    status: number;
    message: string;
    }
    
    或者,更好的做法是使用联合,为成功和错误响应声明不同的类型。这样,TypeScript就不会让我访问属性,除非先检查响应是否成功。像这样利用TypeScript的类型系统可以让代码更容易维护。
    interface DataProps {
    auth: User[];
    }
    interface ErrorResponse {
    status: number;
    message: string;
    error: true;
    errorDetails?: ErrorDetails; // for example
    }
    type SuccessResponse<T> = T & {
    status: number;
    message: string;
    error?: false;
    }
    export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse<DataProps>
    ) {