node.js - 打字稿:'数字| undefined' 不可分配给“number”类型的参数
问题描述
我有一个带有 Activiy 接口和 Mongo Schema 的模型,以及一个接受 ID 并记录它的函数。然后在我的路线中,我查询来自未定义 externalId 的给定客户的所有活动。使用返回的数组,我调用模型中定义的函数,将 externalId 作为参数传递。
但是 TypeScript 一直在抛出:'number | 类型的参数 undefined' 不能分配给“number”类型的参数。类型“未定义”不可分配给类型“数字”。我已经尝试用 if 语句检查 if 来包装调用externalId && typeof externalId === 'number'
,但我不能让错误消失。
模型:
import { Schema, model, } from 'mongoose';
interface IActivity {
customer: string,
externalId?: number,
}
const activitySchema: Schema = new Schema({
Customer: {
type: String,
required: true,
minlength: 5,
maxlength: 50,
},
externalId: { type: Number, },
});
export function updateExternal(externalId: number): void {
console.log(externalId);
}
export const Activity = model<IActivityModel>('Activity', activitySchema);
路线:
const completeActivity = await Activity
.find({
'externalId': { '$ne': undefined, },
'customer': 'Foo Customer',
});
completeActivity.forEach((activity) => {
updateExternal(activity.externalId); // This is where the error appears
});
解决方案
有趣的是,当键可能没有真正的值时,为了获得键的值应该发生什么。activity.externalId
有类型number | undefined
所以我们该怎么做才能从 tonumber | undefined
移动number
?
我们需要“移除”该类型的那一部分,也就是说,我们需要提供某种方法来将 的所有undefined
部分转换number | undefined
为number
。
通常我们通过提供一些默认值来做到这一点——我们说只要值为undefined
,就不要使用它——改用默认值。但是,使用 typescript 很难找到一个好的类型;我们不能指定对象的类型具有我们正在寻找的属性;所以我们必须简单地说它可以是any
,因此,该函数只能返回any
,如下所示:
interface IX {
a?: number;
}
function propOr<K extends string | number, U, O extends Record<K, U>>(k: K, defaultValue: U, obj: O) {
return obj[k];
}
const testFunction1 = (x: IX) => x.a; // has type number | undefined
const testFunction2 = (x: IX) => propOr('a', -1, x); // type error:
我们在这里得到的类型错误是:
'IX' 类型的参数不能分配给 'Record<"a", number>' 类型的参数。属性“a”的类型不兼容。输入'号码 | undefined' 不可分配给类型 'number'。类型“未定义”不可分配给类型“数字”。(2345)
我们可能会查看其他库,看看它们做了什么,例如,Sanctuary 有它:
prop(p: string): (q: any) => any;
因此,当键入一个函数时,我们有点卡住了,我们被迫丢失类型信息(除非其他人可以跳出更好的主意)。
我能想到的最好的解决方案是只使用 or 总是得到一个数字:
interface IX {
a?: number;
}
const a: IX = {};
const b = a.a || 0;
现在b
有了类型number
。
推荐阅读
- python - 如何从python中的同一目录导入文件?
- sql - excel SQL插入
- python-3.x - FakeRedis 异常 - FakeSocket 没有 fileno() 方法
- css - 如何单独设置 Angular 材质组件的样式?
- javascript - jQuery自动完成过滤表的输入字段
- php - 如何在 Laravel 模型中为带有大写字母的字段设置或获取属性?
- c - 在后台运行时间函数?
- angular - Angular 7 (RxJs6) - 单元测试 - 如何检查服务是否返回 throwError?
- javascript - 当 2 个状态相同时运行 setState
- java - Java:获取给定时间范围内的电子邮件,以该格式进行查询