Determine the type of a Typescript property with reflection at runtime

When forwarding TypeScript to JavaScript, I understand that TypeScript's type information is lost and features like reflection will only work very limitedly. We use JavaScript reflection at runtime, which understandably limits our "knowledge" of TypeScript types.

Could there be a way to get TypeScript type information at runtime?

Let's take the following snippet available at codepen.io :

class Book {
    public title: string;
    public isbn: string;
}

class Author {
    public name: string = '';
    public books: Book[] = [];

    constructor() {
        const r = Reflect.getOwnPropertyDescriptor(this, 'books');

        console.log(`typeof: ${typeof this.books}`);
        console.log(`constructor: ${this.books.constructor.name}`);
        console.log(r);
    }
}

const author = new Author();

      

The logs output "object", "array" and:

Object {
    configurable: true,
    enumerable: true,
    value: [],
    writeable: true
}

      

I want to loop over Author properties and define the type of Author.books or any property. I expect to be able to establish at runtime that Author.books is an array of books. Just knowing that it is an object or an array does not help with what I am trying to achieve at all.

Any ideas on how this can be achieved?

+3


source to share


1 answer


I'm going to jeopardize the answer and say that it can't be done with what's available to you by default - you need to parse d.ts

to get a true reflection of all types.

How do you say; an array is an instance Array

, the only way to infer what type the array should contain is by passing the class of the required type. So, you can do something like this:

class Book {
  public title: string;
  public isbn: string;
}

type Newable<T> = {
  new (): T;
}

class Author<T> {
  public name: string = '';
  public books: T[] = [];

  constructor(bookRef: Newable<T>) {
    console.log(`name: ${bookRef.name}`);
  }
}

const author = new Author(Book);

      

Not surprising, and it only works if the book is a class.



typescript can also infer the type you are using for the book from what you pass to the constructor:

enter image description here

bookRef.name

will get the class name at runtime.

+3


source







All Articles