I am trying to create a generic class to define a resource which has crud operations. My end goal is to have a generic class instance that can be used to create services, reducer slices and components to automatically display data, filter and paginate a particular resource. For the current use case this is what I want to define
Resource City has parents state and country CityInstance.getPath should accept ids for state and country and 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;
}
//I want the argument parentIds to include every single element of parents and their ids
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"]})
//The next call should force me to supply the object of ids and should not allow calls without them such as this one
resource.getBaseUrl({}) // Typescript should not allow
resource.getBaseUrl({country: 1}) // Typescript should not allow.
//This would be valid since it supplies both state and country
resource.getBaseUrl({country: 1, state:2});
I realize that typescript cannot predict what the runtime values would be and therefore cannot infer types from the code alone. I have tried creating parents as a type but don't know how to work with that
class Resource<ResourceType, Parents extends string[] =[] > {
name:string
resourceUrlName:string
constructor(name:string,resourceUrlName:string){
this.name=name
this.resourceUrlName = resourceUrlName
}
//How do I specify that the indexer should be a part of parents array type
generateBasePathForCollection(parents: {[name: keyof Parents} : number}){
// How do I get all the members of the Parents Array
}
}