Home > OS >  Describing a Typescript constructor for a class with generic types
Describing a Typescript constructor for a class with generic types

Time:07-01

There's a function I use in testing:

export function cast<T>(obj: any, klass: new (...args: any[]) => T): T {
  if (!(obj instanceof klass)) {
    throw new Error(`Not an instance of ${klass.name}: ${obj.constructor.name}`);
  }
  return obj;
}

which is used like this.

interface I {...}
class C implements I {...};

const i: I = ...;
const c = cast(i, C);

However, if I try to use generics, the compiler complains string in the call.

interface I<T> {...}
class C<T> implements I {...};

const i: I<string> = ...;
const c = cast(i, C<string>);
                    ~~~~~~

Type 'any' has no signatures for which the type argument list is applicable. ts(2635)

Any thoughts on how I can make a version of cast that is friendly to generics? Even if it can't verify that instances in i are of type string, finding a way to get it to compile would be useful (otherwise I have to use as anyway.)

TypeScript cast type using generics and constructor? looks close, but seems bound to a specific type hierarchy.

CodePudding user response:

Answer

Requires Instantiation expression pattern added in TS4.7.0 https://github.com/microsoft/TypeScript/pull/47607. C<string> fails to compile because before 4.7 there was no support to instantiate generic functions/classes with a specific type parameter. Short of upgrading version, there isn't really a terse or compact workaround (I know of). I have done a workaround for instantiation expressions here, but for functions, and it may or may not be of any use.

Workaround

You'll have to explicitly declare C<string> as the generic parameter.

const c = cast<C<string>>(i, C)

Or you can create an instantiator function (although this will only work on class C)

export const I = <T>(
  Base: new (...args: any[]) => C<T>
) => { 
  return Base
}

export const CString = I<string>(C)

const c = cast(i, I<string>(C))
const c2 = cast(i, CString)
  • Related