In my coding journey, I am exploring the creation of a versatile class that can define and handle CRUD operations for various resources. The ultimate goal is to have a single generic class instance that can be utilized to generate services, reducer slices, and components effortlessly, enabling automatic data display, filtering, and pagination for a specific resource.
For this particular scenario, here is what I aim to accomplish:
The Resource City is linked to state and country as parent entities. When calling CityInstance.getPath with IDs for state and country, it should return /country/1/states/1/cities.
export default class Resource {
name: string;
path: string;
parents: string[];
constructor(arg: { name: string; path: string; parents: string[] }) {
this.name = arg.name;
this.path = arg.path;
this.parents = arg.parents;
}
//Requirement: Include all parent elements and their respective IDs in parentIds
getBaseUrl(parentIds: {[parentName:string]: id}){
const parentPath = this.parents.map(p=>`/${p}/${parentIds[p]}`).join("");
return `${parentPath}/${this.path}`
}
}
const resource = new Resource({name:"city", parents: ["countries", "states"]})
//Next call must provide IDs object, disallowing calls without them like this one
resource.getBaseUrl({}) // Should not be allowed by Typescript
resource.getBaseUrl({country: 1}) // Should also not be allowed by Typescript.
//Valid call since it provides both state and country IDs
resource.getBaseUrl({country: 1, state:2});
While working on this project, I encountered challenges with TypeScript's type inference. Even though runtime values cannot be predicted, I attempted to define parents as a type but faced obstacles in implementation.
class Resource<ResourceType, Parents extends string[] =[]> {
name:string
resourceUrlName:string
constructor(name:string,resourceUrlName:string){
this.name=name
this.resourceUrlName = resourceUrlName
}
//How can I specify that the indexer should adhere to the parents array type?
generateBasePathForCollection(parents: {[name: keyof Parents}: number]){
// How do I access all members of the Parents Array?
}
}