I am working with an interface that defines scenes and their parameters:
export interface IScene<R extends string> {
path: R;
params?: SceneParams;
}
The SceneParams interface looks like this:
export interface SceneParams {
[key: string]: string;
}
Creating scene types works well, for example:
interface PostDetailScene extends IScene<PostRoute.Detail> {
params: PostDetailSceneParams;
}
In the above code snippet, PostDetailSceneParams can be defined as:
export interface PostDetailSceneParams extends SceneParams {
postId: string;
}
All type checks are correct in the following examples:
// CORRECT
getPathWithParams({
path: PostRoute.Detail,
params: { postId: '4' },
});
getPathWithParams({
path: UserRoute.List,
});
getPathWithParams({
path: UserRoute.List,
params: undefined,
});
// ERROR
getPathWithParams({
path: PostRoute.Detail,
params: undefined,
});
getPathWithParams({
path: PostRoute.Detail,
});
getPathWithParams({
path: UserRoute.List,
params: { wrongParam: 'value' },
});
Now, when dealing with a scene where no props need to be passed, such as UserListScene:
interface UserListScene extends IScene<UserRoute.List> {
params?: never;
}
The question arises whether there is a way to alter the IScene interface so that explicitly typing params?: never
or params?: undefined
when no parameters are needed can be avoided. Ideally, it would look like this:
interface UserListScene extends IScene<UserRoute.List> {}
or:
type UserListScene = IScene<UserRoute.List>;
EDIT:
The function for retrieving paths with parameters should also undergo proper type checking:
export function getPathWithParams(scene: Scene): string {
if (!scene.params) {
return scene.path;
}
let pathWithParams: string = scene.path;
const paramsAsString = Object.keys(scene.params);
paramsAsString.forEach((param: string) => {
pathWithParams = pathWithParams.replace(`:${param}`, scene.params[param]);
});
return pathWithParams;
}