使用时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)
Run Code Online (Sandbox Code Playgroud)
我知道有一个现有的帖子有一个很好的答案,但由于推断这种情况的解决方案(映射到可选子属性)并不容易,并且我在过去几天不得不做同样的事情,我将分享这个这里。
const gpsLocationList = allHouses
.filter((house): house is House & {location: GPSLocation} => {
return house.location !== undefined;
})
.map(house => house.location);
Run Code Online (Sandbox Code Playgroud)
为了清楚起见,我宁愿将其分成一个单独的声明。
type HouseLocationRequired = House & {location: GPSLocation};
const gpsLocationList = allHouses
.filter((house): house is HouseLocationRequired => {
return house.location !== undefined;
})
.map(house => house.location);
Run Code Online (Sandbox Code Playgroud)
如果你想真正减少类型的重复,你可以使用Required<T>和Pick<>
type HouseLocationRequired = House & Required<Pick<House, "location">>;
Run Code Online (Sandbox Code Playgroud)
并将其进一步抽象一层:
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);
Run Code Online (Sandbox Code Playgroud)
此时,您还可以使用类型安全来抽象检查子属性。
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)
Run Code Online (Sandbox Code Playgroud)
那么为什么不抽象整个过程,将映射添加到该子属性呢?
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");
Run Code Online (Sandbox Code Playgroud)
请参阅实时示例,该示例显示了当您使用这些实用程序时这些建议是多么棒。
| 归档时间: |
|
| 查看次数: |
1153 次 |
| 最近记录: |