I have an abstract class, in the method of which I am passing an item of a generic type. Next, I need to get the property of this item, how to do it correctly?
export abstract class BaseService<T> {
...
public saveItem(item: T) {
...
if (item.id <=== here I got error ) {
}
...
}
export class ClusterItem {
id: number;
...
}
export class ClustersService extends BaseService<ClusterItem> {
...
}
Your code assumes that every type T
used with your class may have an id
property.
As pointed out by Jon Sharpe in his comment on your question, the correct approach, both in terms of type safety and expressiveness, is to declare this assumption as a type constraint, making it explicit and known to the type checker.
The way to do this is to use the type constraint syntax on your generic type parameter.
For example, you could write
export interface MayHaveId {
id?: number; // you can use any type, number is just an example
}
export abstract class BaseService<T extends MayHaveId> {
saveItem(item: T) {
if (item.id !== undefined) {
console.log(item.id);
}
}
}
Here we've defined an interface to make the code more readable, but a type literal would work as well.
Note that the id
property is declared optional since your logic does not require it to have a value.
If you only intend for the base class to be used with type arguments which do have an id
then you should make the property required. This will make the code easier to understand and will catch more errors at compile time by ensuring that it is only used with such types in the first place.
Shahbaaz asked about dynamic properties in a comment.
We can define a type with a dynamic property by using a parametric generic type
type WithProperty<K extends string, V = {}> = {
[P in K]: V
}
We can consume this type
function withProperty<T, K extends string, V> (x: T, properties: WithProperty<K, V>) {
return Object.assign(x, properties);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With