gpt4 book ai didi

Typescript 和 Array.filter() 协同工作

转载 作者:行者123 更新时间:2023-12-02 16:05:03 25 4
gpt4 key购买 nike

当使用 Array.filter() 时,我不确定如何实现我在下面描述的内容。

我不想为此创建一个新类型(但如果没有其他办法,那没关系):

interface GPSLocation {
lat: number
lng: number
}

interface House {
address: string
location?: GPSLocation
}

const house01: House = {
address: '123 street'
}

const house02: House = {
address: '123 street',
location: {
lat: 111.111,
lng: 222.222
}
}

const allHouses = [house01, house02]

// Infered by Typescript: const gpsLocationList: (GPSLocation | undefined)[]
// Expected: const gpsLocationList: (GPSLocation)[]
const gpsLocationList = allHouses.filter((house) => house.location !== undefined).map(house => house.location)

最佳答案

让你的过滤器回调成为一个type guard这会强制 location 不是可选的。

我知道有一个现有的帖子 with a great answer , 但由于推断这种情况的解决方案(映射到可选子属性)并不那么容易,而且我在过去几天不得不做同样的事情,所以我将在这里分享。

const gpsLocationList = allHouses
.filter((house): house is House & {location: GPSLocation} => {
return house.location !== undefined;
})
.map(house => house.location);

为了清楚起见,我更愿意将其拆分为单独的声明。

type HouseLocationRequired = House & {location: GPSLocation};

const gpsLocationList = allHouses
.filter((house): house is HouseLocationRequired => {
return house.location !== undefined;
})
.map(house => house.location);

如果你想真正减少类型的重复,你可以使用Required<T>Pick<>

type HouseLocationRequired = House & Required<Pick<House, "location">>;

再抽象一层:

type RequiredSubProperty<Class, Prop extends keyof Class> = Class & Required<Pick<Class, Prop>>;

const gpsLocationList = allHouses
.filter((house): house is RequiredSubProperty<House, "location"> => {
return house.location !== undefined;
})
.map(house => house.location);

此时,您还可以抽象检查具有类型安全的子属性。

function subPropFilter<T>(prop: keyof T) {
return (obj: T): obj is RequiredSubProperty<T, typeof prop> => {
return obj[prop] !== undefined;
}
}

const gpsLocationList = allHouses.
.filter(subPropFilter("location"))
.map(house => house.location)

那么为什么不将整个过程抽象为子属性添加映射呢?

function getNonNullSubProps<T, Prop extends keyof T>(arr: T[], prop: Prop) {
return arr.filter(subPropFilter(prop)).map(obj => obj[prop] as typeof obj[Prop])
}

const gpsLocationList = getNonNullSubProps(allHouses, "location");

参见 live example这表明在您使用这些实用程序时这些建议是多么棒。

关于Typescript 和 Array.filter() 协同工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69651602/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com