Type guard for property
snamiki1212 opened this issue · comments
Hi, thank you for your awesome utils. I'm thinking of using this library because I want to check the property is not undefined but it looks isPropertyNotUndefined
only returns boolean without type-guard.
import { isPropertyNotUndefined } from 'typesafe-utils';
const list: Array<{
lat: number | undefined,
lng: number | undefined,
}> = [];
const nonTypeSafe = list.filter(item => !!item.lat && !!item.lng);
const typeSafeButNotWorking = list.filter(isPropertyNotUndefined('lat')); // not working
// expect { lat: number, lng: number | undefined; }[]
// but type is { lat: number | undefined; lng: number | undefined; }[]
So, I enhanced isPropertyNotUndefined
like following code.
// =====================
// Codes
// =====================
type NonNullableBy<T, K extends keyof T> = {
[P in keyof T]: P extends K ? NonNullable<T[P]> : T[P];
};
export const isPropertyNotUndefined = <T, K extends keyof T>(
property: K
) => (obj: T): obj is NonNullableBy<T, K> => obj[property] !== undefined
// =====================
// Examples
// =====================
type Geo = {
lat: number | undefined,
lng: number | undefined,
};
const list: Array<Geo> = [];
const nonTypeSafe = list.filter(item => !!item.lat && !!item.lng);
{
const typeSafe1 = list.filter(isPropertyNotUndefined('lat')); // => NonNullableBy<Geo, "lat">[]
const {lat, lng} = typeSafe1[0]; // => lat: number, lng: number | undefined
}
{
const typeSafe2 = list
.filter(isPropertyNotUndefined('lat'))
.filter(isPropertyNotUndefined('lng')); // => NonNullableBy<NonNullableBy<Geo, "lat">, "lng">[]
const {lat, lng} = typeSafe2[0]; // => lat: number, lng: number
}
This enhanced code can work with type guard but return type is a bit ugly. I'm not sure arePropertiesNotUndefined
will be similarly enhanced.
Do you have any ideas about it? I would create PR If it would be preferred.
Hi @snamiki1212 thanks for looking into this.
I haven't updated the code since a while. A PR would be great to fix the type guard here. I think it is also possible to simplify the type definitions, but I don't have time to take a deeper look into this in the coming weeks as I'm on vacation.
No rush take your nice vacation🏖️