How to use DataService when my entity has no 'id' property?
alcaidio opened this issue · 3 comments
Is it possible to use an adapter to map my "id" property to "someId"?
Hey @alcaidio, yes, it should be possible to implement it. If you want to contribute, PRs are always welcomed.
I would be interested in that feature, too! Unfortunately I am not sure how to contribute a solution yet but I wanted to share my current workaround, in case anybody else ends up here, too.
First, I create a type to annotate the DataService with. Because it is just an extension, it should not break code already written. In my case, I just need to map an already existing attribute to id
, so if I don't delete it, my code ist still working.
type WithIdGetter<T, K extends keyof T> = T & {
get id(): T[K];
};
As my backend only returns elements of type T
without the id attribute, I also wrote a generic mapper function
function mapToIdGetter<T, K extends keyof T>(items: T[], key: K): (T & { get id(): T[K] })[] {
return items.map((item) => ({
...item,
get id() {
return item[key];
},
}));
}
Again, it just adds a getter to my interface. As you can see, it works on a list of items. The principle would be very similar for just one element (you just leave out the list type and map function).
Update: microsoft/TypeScript#58020 Due to this bug, I replaced the getter by a hardcoded item
export type WithIdGetter<T, K extends keyof T> = T & {
id: T[K];
};
export function mapToIdGetter<T, K extends keyof T>(items: T[], key: K): (T & { id: T[K] })[] {
return items.map((item) => ({
...item,
id: item[key],
}));
}
type Product = WithIdGetter<PreviousType, 'uuid'>;
const productCollection = 'products';
export const productState = signalStore(
{ providedIn: 'root' },
withDevtools('ProductsSignal'),
withCallState({collection: productCollection}),
withEntities({
entity: type<Product>(),
collection: productCollection,
}),
withDataService({
dataServiceType: ProductService,
filter: {},
collection: productCollection,
}),
withHooks({
onInit: (store) => {
console.log('loading'), store.loadProductsEntities();
},
}),
);
This store is working fine for me (I need to use it somewhere for it to work)