The current implementation of the code lacks a direct connection between the navigationKey
and params
variables, despite both being determined by a ternary operation based on the currentScreenRoute
.
To achieve the desired type inference, it is suggested to build complete objects within the conditionals themselves rather than separately.
type EngagementGroup = {
inviteCode: string;
// ...
};
function navigateOptions(
currentScreenRoute: 'addGroup' | 'addGroupOnboarding',
group: EngagementGroup
) {
const navigationKey: 'addGroupPeople' | 'addGroupQR' = currentScreenRoute === 'addGroup' ? 'addGroupPeople' : 'addGroupQR';
if (navigationKey === 'addGroupPeople') {
return {
navigationKey,
params: {
group,
inviteCode: group.inviteCode,
showGroupCreatedToast: true,
}
}
}
else {
return {
navigationKey,
params: {
inviteCode: group.inviteCode,
}
}
}
}
/*
Return type:
{
navigationKey: "addGroupPeople";
params: {
group: EngagementGroup;
inviteCode: string;
showGroupCreatedToast: boolean;
};
} | {
navigationKey: "addGroupQR";
params: {
inviteCode: string;
group?: undefined;
showGroupCreatedToast?: undefined;
};
}
*/
Since no types are explicitly declared, TypeScript deduces the type of params
, assuming both objects share the same type but with optional properties.
A more robust approach would be to define specific types for these scenarios and use a discriminated union to represent the possible return options.
type AddGroupPeopleNavigationOption = {
navigationKey: 'addGroupPeople',
params: {
group: EngagementGroup;
inviteCode: EngagementGroup['inviteCode'];
showGroupCreatedToast: true
}
}
type AddGroupQrNavigationOption = {
navigationKey: 'addGroupQR';
params: {
inviteCode: EngagementGroup['inviteCode'];
}
}
type NavigationOption = AddGroupPeopleNavigationOption | AddGroupQrNavigationOption
function navigateOptions(
currentScreenRoute: 'addGroup' | 'addGroupOnboarding',
group: EngagementGroup
): NavigationOption {
const navigationKey: NavigationOption['navigationKey'] = currentScreenRoute === 'addGroup' ? 'addGroupPeople' : 'addGroupQR';
if (navigationKey === 'addGroupPeople') {
// TypeScript expects the type of params here to match AddGroupQrNavigationOption['params']
return {
navigationKey,
params: {
group,
inviteCode: group.inviteCode,
showGroupCreatedToast: true,
}
}
}
else {
// TypeScript expects the type of params here to match AddGroupPeopleNavigationOption['params']
return {
navigationKey,
params: {
inviteCode: group.inviteCode,
}
}
}
}
If an incorrect params
object is provided that does not align with the inferred type based on the value of navigationKey
, TypeScript will now raise an error.
TypeScript Playground