猫鼬(打字稿):输入 'string |解析Qs |字符串[] | ParsedQs[]' 不可分配给类型 'Condition<string>'

时间:2021-07-02 09:53:40

标签: node.js typescript mongodb mongoose

用这样的打字稿接口定义猫鼬模型:

import { Schema, model, Document } from 'mongoose';

export interface IUserInfo extends Document {
  userId: string;
  email: string;
}

const UserInfoSchema:Schema = new Schema<IUserInfo>({
  userId: { type: String, unique: true },
  email: String
}, { timestamps: true });

export const UserInfoModel = model<IUserInfo>('userInfo', UserInfoSchema);

使用 UserInfoModel 通过像这样的猫鼬方法通过 userId 获取电子邮件:

const user: IUserInfo = await UserInfoModel.findOne({ userId: req.query.userId });

userId 上收到此错误:

Type 'string | ParsedQs | string[] | ParsedQs[]' is not assignable to type 'Condition<string>'.
  Type 'string[]' is not assignable to type 'Condition<string>'.
    Type 'string[]' is not assignable to type 'string'.

166     const user: IUserInfo = await UserInfoModel.findOne({ userId: req.query.usreId });
                                                       ~~~~~~

  src/models/userInfo.ts:4:3
    4   userId: string;
        ~~~~~~
    The expected type comes from property 'userId' which is declared here on type 'FilterQuery<IUserInfo>'

我不知道我在这里做错了什么。

2 个答案:

答案 0 :(得分:1)

问题是 findOne expects 在这里输入 FilterQuery<IUserInfo>。类型 FilterQuery 具有漂亮的 complex 结构。但在您的情况下,本质上归结为这样一个事实,即它期望一个对象,其中 userId 字段必须具有类型 string

express 用于解析查询字符串 qs 库。其中解析查询字符串的结果 (req.query) 为 typed 如下:

interface ParsedQs { [key: string]: undefined | string | string[] | ParsedQs | ParsedQs[] }

您可能会注意到,虽然消费函数 findOne 只需要一个 string,但 req.query.userId 可以提供多种可能的结果类型。

从打字稿的角度来看,这是一个危险信号。想象一下,我们强烈期待一个字符串并立即 lowerCase 它,但接收的是一个字符串数组:

function lowerCase(str: string) {
    return str.toLowerCase() // totally type safe operation assuming input type
}

const stringOrArr: string | string[] = []

lowerCase(stringOrArr) // throws an error

因此,要提供 findOne 您的 req.query.userId,您必须narrow 它的类型为消费函数可接受的类型。

const user: IUserInfo = 
    await UserInfoModel.findOne({ userId: req.query.userId as string });
function assertString(str: unknown): asserts str is string {
    if (typeof query.userId !== 'string') throw new Error('Must be a string')
}

assertString(req.query.userId);

const user: IUserInfo = 
    await UserInfoModel.findOne({ userId: req.query.userId }); // no error now

答案 1 :(得分:0)

解决方案


export interface Person {
  name: string;
  last: string;
}

export class PersonDoc extends mongoose.Document implements Person {}

export type PersonModel = mongoose.Model<PersonDoc>;

const personSchema = new mongoose.Schema<PersonDoc, PersonModel, Person>({
  name: { type: mongoose.SchemaTypes.String, required: true },
  last: { type: mongoose.SchemaTypes.String, required: true },
})

在 yow 模式定义中使用它们 mongoose.SchemaTypes,而不是通常使用的普通类型。