ken
ken

Reputation: 8993

<T extends Error> not resolving in Typescript

I have an interface defined as:

export interface IErrorIdentification {
  errorClass?: new <T extends Error>() => T;
  code?: string;
  name?: string;
  messageContains?: string;
}

The errorClass property, however, is giving me fits. When using this code:

context.errorMeta.add(
  404,
  { errorClass: HandledError },
  { callback: e => cbResult }
);

Where the second parameter -- { errorClass: HandledError } -- is typed to IErrorIdentificaiton I get the following error:

error

It works as expected at run time with the following check:

e instanceof i.identifiedBy.errorClass

The error (e) also tests positive as an instance of Error which makes sense considering HandledError is defined as:

export class HandledError extends Error { ... }

Given all this, i'm unsure why I'm getting an error at all and the error text isn't helping me. Can anyone point me to what I'm doing wrong?

Upvotes: 1

Views: 336

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70267

errorClass?: new <T extends Error>() => T;

This doesn't mean what you think it means. It means "errorClass should be a generic thing on which I can invoke new and get any error type of my choice." That is, for all T extending Error, new should be able to return a T. HandledError doesn't satisfy this, because it can't return, say, TypeError or any other type of error. In all honesty, I'm not sure Typescript has any way of constructing a (non-any) value which satisfies that constraint.

What you want is something that says "there exists some T for which new returns a T". That's called an existential type, which Typescript does not support. So you have a couple of options. If you don't care about the specific type of error, just drop the facade and have new return Error.

export interface IErrorIdentification {
  errorClass?: new() => Error;
}

On the other hand, if you really need the T value for whatever reason, parameterize your interface.

export interface IErrorIdentification<T extends Error> {
  errorClass?: new() => T;
}

Upvotes: 3

Related Questions