javascript - TypeScript 说 Intersection 属性不存在
问题描述
我有一个变量,它以一种类型开始IPerson[]
,但是在映射了几次之后,应该_id
添加一个属性,比如Array<IPerson & IWithId>
. 但是,在倒数第四行中,打印该_id
属性会给我一个 TS 错误,即使该属性确实存在并且日志记录工作如我所料,打印三个属性fname
、lname
和_id
。
我想也许我需要以某种方式重新投射它,比如
mapped = collection.map(mapperB) as Array<IPerson & IWithId>
mapperB
那没有用,谢天谢地,因为对于 imo 应该已经根据函数的返回类型获取其类型的变量,必须这样做似乎非常冗长。
let _id = 0;
interface IPerson {
fname: string;
lname: string;
}
interface IWithId {
_id: number;
}
function getNumber() {
return _id++
}
async function getData(json: string): Promise<IPerson[]> {
return JSON.parse(json)
}
function mapperA(entry: IPerson): IPerson {
return {
...entry,
lname: entry.lname.toUpperCase()
}
}
function mapperB(entry: IPerson): IPerson & IWithId {
const _id = getNumber();
return {
...entry,
_id
}
}
async function main() {
const json = `[{"fname":"john","lname":"doe"},{"fname":"jane","lname":"doe"}]`
const collection = await getData(json)
let mapped = collection.map(mapperA)
mapped = collection.map(mapperB)
console.log(mapped[0]._id); // Property '_id' does not exist on type 'IPerson'.
return mapped;
}
main().then(console.log)
如果我使用另一个变量来保存第二个映射函数的值,我可以让它工作,即const mapped2 = collection.map(mapperB)
但我很好奇为什么我不能使用我的原始变量?
为什么打字稿不mapped
从明确声明的返回值推断出的值mapperB
?我可以让它为我做这个吗?
解决方案
TypeScriptmapped
从它的第一个赋值(初始化)推断出类型,所以它是IPerson[]
:
In TypeScript, there are several places where type inference is used to provide
type information when there is no explicit type annotation. For example, in this
code
> let x = 3;
The type of the x variable is inferred to be number. This kind of inference takes place
when initializing variables and members, setting parameter default values, and
determining function return types.
摘自TypeScript 手册中的“类型推断”一章(我链接了它即将发布的 2.0 beta 版本),我建议阅读这个。
然后第二个赋值不会扩展定义,但也没有错误,因为对象可以具有其他属性。当您访问_id
时,您会收到一个错误,因为 TypeScript 无法从最初推断的类型确定数组条目也包含_id
属性。
注意:casting withmapped = collection.map(mapperB) as Array<IPerson & IWithId>
不会给 TypeScript 额外的信息,所以结果是一样的。
为了简化类型的推理,我个人建议将转换后的值分配给新变量(正如您建议的那样const mapped2 = collection.map(mapperB)
。并选择富有表现力的变量名称(权衡变得冗长,但如果您保持函数复杂性足够小,这种情况不应该经常发生) :
const filteredList = list.filter(...);
const filteredListWithIds = filteredList.map(...)
没有直接关系,而是一个错误:Array.prototype.map()
返回一个新数组。mapped
from的值在映射 = collection.map(mapperB)`let mapped = collection.map(mapperA)
时立即丢失。s being overwritten at the next line during
根据您的真实代码创建游乐场示例时可能会出错?
推荐阅读
- python - 使用 pyplor LogLocator 的连续色标和良好范围
- reactjs - S3 bucket next js 私下访问图片
- sql - 如何提高包含部分公共子查询的 SQL 查询性能
- python-3.x - 读取数据框中的列
- skyfield - 试图在给定时间计算行星天空中的方向,但得到不正确的答案?
- apache - 重写 Apache Query_String
- javascript - JQuery ajax JSON数据数据丢失
- python-3.x - Python3 字符串格式化与 . 在前面失踪
- python - 如何将多个但特定的行从一个数据帧添加到另一个数据帧
- javascript - PrimeFaces 渲染的所有 JavaScript 是什么?