0

I have the following types in Typescript:

type Task<T> = () => Promise<T>;
type QueueItem<T> = { task: Task<T>; resolve: (v: T) => void; reject: () => any };

I have a class that uses these types:

class Queue {
  private queue: QueueItem<T>[] = [];
  insertTask<T>(task: () => Promise<T>): Promise<T> {
    const promise = new Promise((resolve, reject) => {
      this.queue.push({ task, resolve, reject });
    });
    return promise;
  }
}

Im trying to define a new type that is an array of QueueItem<T>. I have tried:

queue = [] as QueueItem<T>[];

queue: QueueItem<T>[] = [];

queue<T>: QueueItem<T>[] = [];

But none worked. I keep getting the following error:

Cannot find name 'T'.ts(2304)

How can I define it correctly?

You can try it in this demo

3
  • Not quite sure what T is supposed to represent in this case. Did you mean class Queue<T>? There is no point to having a generic property to a non generic class. Commented Jan 21, 2020 at 9:19
  • Just adding the method of the class that uses the array, not sure if it makes any difference. The syntax of class Queue<T> is strange, do I have to add every generic type variable that uses the class in the top of the class? :/ Commented Jan 21, 2020 at 9:45
  • @Rashomon updated your defintion of resolve, it matters to the variance of QueueItem how T is used Commented Jan 21, 2020 at 10:02

2 Answers 2

3

You can't have a variable that is typed with an open type parameter. You can use unknown (if T is covariant), never (if T is contravariant) or any (works for T invariant or any other varinance but is less safe)

In your case T appears in both covariant (in task) and in a contravariant position (in position in resolve) so any is the only choice:

type Task<T> = () => Promise<T>;
type QueueItem<T> = { task: Task<T>; resolve: (v:T) => void; reject: () => any };


class Queue {
  private queue: QueueItem<any>[] = [];

  insertTask<T>(task: () => Promise<T>): Promise<T> {
    const promise = new Promise<T>((resolve, reject) => {
      this.queue.push({ task, resolve, reject });
    });
    return promise;
  }
}```
[Playground Link](https://www.typescriptlang.org/play/?ssl=14&ssc=2&pln=1&pc=1#code/C4TwDgpgBAKghgZwNYB4YD4oF4oAoCU2mACgE4D2AtgJYIRroDcAUKJFAIoCuEPAksAiUG2KAG8owREgBcsaQ0ZRSEBOQA2ANwhzcmmTEJZMm8tQAmSlQCsIAY2C6jmOADsQUAL4tmzO+sQETh4ecWYoKDBSak04QSgARxCdYN4IASEUNxB0AG0AXVEClgjwqGpXOlJgeGQGXClkJyIoMipaegx8OTaaOhExMoi7ckrgSIo+6BxXCAB3VsmO+twVNS0IABplCFsHZzCIo8kAC1oAOiS087AuBBPcCUakbbWNbVfd+3HPfBKj37-CIqYBcUiuCbtOj-TzMTxAA)

Since you are inserting many different `T` in `queue` there is no way to preserve the types off all of these. If you were to give all the tasks to ever be executed in the `Queue` constructor you could use a tuple type, but that seems to be antithetical to the point of the `Queue`.


Another option is to make `Queue` generic if you just need to forward the type parameter:


```ts
type Task<T> = () => Promise<T>;
type QueueItem<T> = { task: Task<T> };

class Queue<T> {
  private queue: QueueItem<T>[] = [
  ];
}

Playground Link

Sign up to request clarification or add additional context in comments.

3 Comments

@Rashomon The unknown solution holds, I would even advise against adding the T parameter in insertTask as that type info will be lost anyway and seems to serve no other purpose in the insertTask methods itself (it does not constrain any parameters or the return type in any way).
You are right. I was trying to generate a minimal example of my problem, and realized it wasnt the same (:facepalm:). I actually use Promise<T> for the return. I will upvote you, and... if you can check it again, it would very helpful :)
@Rashomon checked again, now T is indeed useful for the clients of Queue, but as to the internal representation of the queue, any becomes the only viable option (since T is now invariant for QueueItem. It appears both in a return type and and as a parameter to a function )
0

The Query class is missing the T generic, so typescript do know of which type the queue items are.

class Queue<T> {
  private queue: QueueItem<T>[] = [];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.