1

In Typescript we have way to access types from array as below.

const list = [item,item2] as const;
type typeOfArray = typeof list[number];

const something: typeOfArray = ; // item | item2

I have attempted to get that with class but getting "Property 'prototype' is missing in type error"

If I declare classes as type it works fine but can't access through typeof. Is this shortcoming of Typescript? If you have solution, will appreciate your help.

please use below code as sample setup:

class A {
  methodA() {

  }
}

class B {
  methodB() {
    
  }
}

class C {
  methodC() {
    
  }
}

const classList = [A,B,C] as const;

This works just fine:

type classSelection = A | B | C;
let o: classSelection;

o = new A();
o. // o.methodA;

This is giving above error:

type classSelection = typeof classList[number];
o = new A();  //Type 'A' is not assignable to type 'typeof A | typeof B | typeof C'.
  Property 'prototype' is missing in type 'A' but required in type 'typeof C'
3
  • 2
    Your ClassSelectionType is a union of constructor types; if you want to turn that into a union of instance types you can use the InstanceType utility type like this; if that meets your needs I can write up an answer; let me know. Commented Jan 7, 2022 at 19:32
  • This is due to classes having both instance and static side at the same time. The semantics of typeof for them changes - with this operator, you get the static side, meaning you can only assign a constructor to o while what you are trying to assign is an instance, hence the error Commented Jan 7, 2022 at 19:33
  • @jcalz that is what I have been looking for. Thanks bunch! If you put as answer I will mark it. Might be helpful since there is no previous question related. Commented Jan 7, 2022 at 20:04

1 Answer 1

2

Your classList variable is an array of class constructors:

const classList = [A, B, C] as const;
// const classList: readonly [typeof A, typeof B, typeof C]

Which means when you index into its type with a number key type, you get a union of those constructor types:

type ClassConstructors = typeof classList[number];
// type ClassConstructors = typeof A | typeof B | typeof C

Class constructors are not themselves instances; instead, they have construct signatures that look like {new (): A} (which means that using the new operator on it with no arguments will yield a value of type A).

There is an InstanceType<T> utility type which takes a type with a construct signature and returns the corresponding instance type. If you apply it to a union of constructor types, you get a union of instance types:

type ClassSelection = InstanceType<typeof classList[number]>;
// type ClassSelection = A | B | C

And then the rest of your code should work:

let o: ClassSelection = new A(); // okay

Playground link to code

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

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.