I've noticed a pattern in my code and I feel like there's a better solution for this.
Let's say I have these basic entities
type User = {
id: string,
}
type Company = {
id: number,
}
enum Member {
Company = "Company",
Member = "Member",
}
Now oftentimes I'm passing around payloads like this
type Payload = {
type: Member,
payload: Company["id"][] | User["id"][] // string[] | number[]
}
Now the question is, can I infer the type of the payload if I have checked the type? Right now I have to declare the type.
if (payload.type === Member.Company)
result = (payload.payload as number[]).map(etc) // have to declare type of array, how to infer?
In order for that to work, you want your Payload
type to be a discriminated union . Right now, your Payload
is a non-union type, each of whose properties is a union; as such, it can accept values you don't want, such as where the type
is Company
but the payload
has an id
from User
. The union should be pushed up to the top level, where you spell out the relationship involved:
type Payload =
{ type: Member.Company, payload: Company["id"][] } |
{ type: Member.Member, payload: User["id"][] };
Now that we have a top-level union, and since each member's type
property is a unit type (only has a single possible value), the compiler will understand checking type
to discriminate the union:
if (payload.type === Member.Company) {
payload.payload.map(x => x + 1); // okay
} else {
payload.payload.map(x => x.toUpperCase()); // okay
}
If you have lots of enum members you might consider making a mapping interface representing the relationship between each enum member and the object it points to, and using it to calculate Payload
so that you don't have to write out a big union with nearly identical {type: Member.XXX, payload: YYY["id"][]}
members:
interface MemberMapping {
[Member.Company]: Company;
[Member.Member]: User;
}
type Payload = {
[K in Member]: { type: K, payload: MemberMapping[K]["id"][] }
}[Member];
/* type Payload = {
type: Member.Company;
payload: number[];
} | {
type: Member.Member;
payload: string[];
} */
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.