我是Typescript的新手,无法确定我是否正确输入了查询结果。这是我的代码的本质...
import mysql2, {Pool} from "mysql2";
const pool: Pool = mysql2.createPool({...}).promise();
interface IUser {
uid : number;
uname : string;
}
class UserController {
public async getUser(id: number): Promise<IUser> {
const [rows]: Array<{rows: IUser}> = await pool.query(
"SELECT * FROM `users` WHERE `email` = ?",["me@me.org"]);
return rows;
}
}
TypeScript编译器(3.3.1)抱怨我的return rows
语句。
TS2740:类型'{rows:IUser;}'缺少以下属性 输入“ IUser”:uid和uname。
如果我忽略// @ts-ignore
的收益,一切都会很好。我把我的物品放回原处,没有任何错误。
我做错什么了吗?
我做了一些更改,但是对于TypeScript为什么不抱怨,我实在感到困惑。似乎根本不对。
class UserController {
public async getUser(id: number): Promise<{rows: IUser}> {
const [rows]: Array<{rows: IUser}> = await pool.query(
"SELECT * FROM `users` LIMIT 3");
return rows;
}
}
这是对的吗?
所以,没有,这都是错误的。
当我想到query
返回[rows, fields]
时,它也变得更加有意义。我认为@ joesph-climber经过一些调整后的语法是正确的。
这对我来说很有效...
class UserController {
public async getUser(id: number): Promise<Array<{rows: IUser}>> {
const [rows]: [Array<{rows: IUser}>] = await pool.query(
"SELECT * FROM `users` LIMIT 3");
return rows;
}
}
这也可行,并且可能更容易理解。
class UserController {
public async getUser(id: number): Promise<IUser[]> {
const [rows]: [IUser[]] = await pool.query(
"SELECT * FROM `users` LIMIT 3");
return rows;
}
}
答案 0 :(得分:1)
// the function should return a Promise that resolves to
{ uid: number, uname: string }
// but typeof rows is
{ rows: { uid: number, uname: string } }
执行示例,我得到的结果是这样的:
[ TextRow { uid: 1, uname: 'foo', email: 'foo@mail.com' } ]
所以 pool.query 返回一个以IUser数组作为第一个元素的数组。
返回多个用户:
class UserController {
// returns all users
public async getUsers(): Promise<Array<IUser>> {
const [rows]: [Array<IUser>] = await pool.query(
"SELECT * FROM `user`", []);
return rows; // rows is Array<IUser> so it matches the promise type
}
}
返回特定用户:
class UserController {
public async getUser(id: number): Promise<IUser> { // Note the
const [rows]: [Array<IUser>] =
await pool.query("SELECT * FROM `user` WHERE `email` = ?",
["foo@mail.com"]);
// If email is unique as it would be expected it will
// return a single value inside an array
// rows is still Array<IUser>
return rows[0]; // rows[0] is an IUser
}
}
答案 1 :(得分:1)
我遇到了相同的错误,所以我在Google中搜索并建立了以下示例:https://github.com/types/mysql2/blob/master/test/promise.ts
所以我的代码就是这样
const [user] = await pool.query<RowDataPacket[]>("SELECT * FROM Users WHERE email = ?", [email]);
if(!user.length) {
throw {
error: true,
message: 'no user founded'
}
}
有了这个,我可以使用vs代码的自动完成功能,并且没有错误
答案 2 :(得分:0)
接受的答案中的方法对我不起作用(typescript@3.5.2
,mysql2@1.6.5
)。这段代码
interface IUserRow {
ssid: string
}
const [rows]: [IUserRow[]] = await pool.query(
'select ssid from user where id = ?',
[session.userId],
)
给我
error TS2322: Type '[RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[], FieldPacket[]]' is not assignable to type '[IUserRow[]]'.
Types of property '0' are incompatible.
Type 'RowDataPacket[] | RowDataPacket[][] | OkPacket | OkPacket[]' is not assignable to type 'IUserRow[]'.
Type 'RowDataPacket[]' is not assignable to type 'IUserRow[]'.
Property 'ssid' is missing in type 'RowDataPacket' but required in type 'IUserRow'.
突出显示[rows]
。
我能够使用所有工具:
interface IUserRow {
ssid: string
}
const [rows] = await pool.query(
'select ssid from user where id = ?',
[session.userId],
)
// This first if statement is a type guard against rows possibly being OkPacket
if (Array.isArray(rows) && rows.length > 0) {
// The casting works fine here
const userRow = rows[0] as IUserRow
if (userRow.ssid !== session.ssid) {
...
}
}
我不是Typescript专家,所以可能有更好的方法!尽管如此,我希望如果有人也对接受的答案有疑问,我可以避免他们的沮丧。
答案 3 :(得分:0)
使用mysql2 @ 1.7.0,typescript @ 3.6.3,@ types / mysql2
该接口必须扩展RowDataPacket:
interface IUser extends RowDataPacket {
ssid: string
}
您可以在此处输入以下类型:
const [rows]: [IUser[], FieldPacket[]] = await connection.query<IUser[]>("SELECT ssid FROM user", [])
或者简单地
const [rows] = await connection.query<IUser[]>("SELECT ssid FROM user", [])
答案 4 :(得分:0)
在尝试设置稍后将要使用的变量时,仅使用pool.query<type>
对我来说是不够的,因为数据类型RowDataPacket
仍在侵犯我的类型...
我最终为pool
的{{1}}函数创建了一个包装器。看起来像这样:
query
这使我可以在项目的其他部分使用type Row = import("mysql2").RowDataPacket
type Ok = import("mysql2").OkPacket
type dbDefaults = Row[] | Row[][] | Ok[] | Ok
type dbQuery<T> = T & dbDefaults
export const db = {
query: async <T>(query: string, params?: Array<any>): Promise<[T, any]> => {
return pool.promise().query<dbQuery<T>>(query, params)
},
}
函数,类似于其他答案
query
但它会剥离RowDataPacket的类型信息,等等...