I have a function which was earlier implemented as follows
export function insertItemInQueue(
queueRef: RefObject<Partial<IMyRow>[]>,
item: Partial<IMyRow>
) {
console.log(item.ID)
queueRef.current.push(item);
}
In order to use generics, I have changed it to
export function insertItemInQueue<ItemType>(
queueRef: RefObject<ItemType[]>,
item: ItemType
) {
console.log(item.ID)
queueRef.current.push(item);
}
However, I now get the TS error: Property 'ID' does not exist on type 'ItemType'.
I understand ItemType could be anything and may not always have ID as its member. How do we get around this?
I was able to get it to compile by using it as item['ID'] as opposed to item.ID. But I am not sure if this is fine? I feel it takes away the point of generics and has a hard dependency on the fact that whatever generic type is passed in must contain a member called ID, which is not really generic?
CodePudding user response:
If you want to enforce at compile-time that this function call should only accept types that have an ID property, you can define the generic type as extending from an object that contains an ID property, like this (if your ID is not a number, just adjust the example)
function insertItemInQueue<ItemType extends { ID: number }>(
queueRef: RefObject<ItemType[]>,
item: ItemType
) {
console.log(item.ID) // no more compiler error
queueRef.current.push(item);
}
Then the compiler checks and enforces the types at call site
insertItemInQueue(queue, { ID: 123 }) // OK
insertItemInQueue(queue, { ID: 123, a: 1, b: "Some text" }) // OK
insertItemInQueue(queue, { ID: null }) // Error: Type 'null' is not assignable to type number
insertItemInQueue(queue, { ID: undefined }) // Error: Type 'undefined' is not assignable to type number
insertItemInQueue(queue, { a: 1 }) // Error: not the right type because the ID property is missing
