TS reporting a non-existing error with Generic Interfaces extension · Issue #28315 · microsoft/TypeScript (original) (raw)

Hello everybody! I was trying to build a queue system class to be extended with other classes.
The first design was about using a common array for multiple elements of different queues mixed together. The second design, instead, was about to use the following queue structure:

{ "": [ { Function }, { Function }, ... ] }

or

{ "": [ { string } ] }

This because I'm going to use two classes (ReplyManager and OperationManager) to extend the queue. These two classes have a different parameter of the array. Therefore I thought to to the model to describe these structures. I came out with this reasoning:

interface QueueObject { // @ts-ignore - Hashable is a string or number yet. ( This might be another bug ) [key: Hashable]: T[] }

The QueueObject is the base object that will bind the two classes which will extend Queue.

interface OperationDescriptior { command: string }

interface ReplyDescriptor { action: Function, previousData?: any }

These are the descriptors of the content of the arrays, one per class.

export type Reply = QueueObject; export type Operation = QueueObject; export type QueueExtendableObject = Reply | Operation;

export type Hashable = number | string;

In the end we have Reply and Operation which are the Real objects I'm going to use, and QueueExtendableObject, which is the one I'm going to use in the Queue class that has the following signature:

class QueueManager { private _queue : T = {} };

I try to populate the queue object and everything goes fine, but in ReplyManager I have the following method:

execute(id: Hashable, data: ReplyData = {}) { let next: Reply = this.get(id); let callback: Function = next.action;

data.previousData = next.previousData || undefined;

let result = callback(data);
// ...

}

and since I have access to the QueueManager, I can use this.get(id), which has the following characteristics:

Code:

protected get(id: Hashable): T { return this._queue[id] && this._queue[id].length ? this._queue[id][0] : { action: () => { } }; }

Return type: QueueObject<ReplyDescriptor>.

I mean, it makes sense, that's what I wanted!

But there is a problem: in execute, action and previousData of next are underlined in red and give this error:

Property (action | previousData) does not exist on type QueueObject<ReplyDescriptor>.

I tried to execute a sample code I wrote to put these class at work and if I log next after this.get, it will return, as expected, an object with both "action" and "previousData" (if exists).

That's why I think this may be a bug.
Since, as you can see, I've already used @ts-ignore once in the code above, this time I just don't want to ignore but understand.

This is the form.

TypeScript Version: 3.1.3

Search Terms:

"property does not exist in interface", "non existing error"

Expected behavior: No alert.

Actual behavior:

The same error applied on two properties:
Property (action | previousData) does not exist on type QueueObject<ReplyDescriptor>

image

Thank you.