How to get property of generic type?

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);
}