как получить подпись типа экземпляра класса

#typescript

#typescript

Вопрос:

Я должен передать структуру страниц моему основному объекту, а затем сделать эти страницы доступными там с автозаполнением. Вот мой рабочий пример:

 interface Adapter{}
interface PageInterface{}

type PageCtor = {new(adapter: Adapter): PageInterface}
class BasePage implements PageInterface{
  constructor(public adapter: Adapter) {}
}
class LoginPage extends BasePage{
  name: string = 'login'
  foo: number
  constructor(public adapter: Adapter) {
    super(adapter)
  }
  go() {
    console.log('Yo, logged in')
  }
}
class LogoutPage extends BasePage{}
class AboutPage extends BasePage{}

class PagesConfig {[key: string]: PageCtor}

type BaseCore<T> = {[key in keyof T]?: T[key]}

class Core<T>{
  pages: BaseCore<T> = {}
  constructor(public adapter: Adapter, pages: PagesConfig) {
    Object.entries(pages).map(([key, value]: [string, PageCtor]) => {
      (this.pages as any)[key] = new value(adapter)
    })
  }
}

interface Pages{
  login: LoginPage
  logout: LogoutPage
  about: AboutPage
}

class CurrentPages{
  [key: string]: PageCtor
  login = LoginPage
  logout = LogoutPage
  about = AboutPage
}


const adapter = {} as Adapter

const core = new Core<Pages>(adapter, new CurrentPages())
  

в этом случае конечный пользователь моего Core класса должен предоставить Pages интерфейс и CurrentPages класс, который выглядит как какой-то король дублирования. Каждый раз, когда конечному пользователю моего класса потребуется добавить новую страницу, он должен добавить ее в двух местах. Как это можно упростить, используя только CurrentPages class или каким-либо другим способом?

Я думаю, что это как-то связано с BaseCore подписью типа:

 type BaseCore<T> = {[key in keyof T]?: T[key]}
  

T[key] в моем случае это будет конструктор класса, как мне изменить его на экземпляр класса?

Ответ №1:

Вы предотвращаете дублирование, но только если удаляете подпись индекса из CurrentPages . Подпись индекса скрывает отображение любых других членов.

Затем вы можете использовать InstanceType условный тип для получения типа экземпляра из типа класса:

 type BaseCore<T extends Record<string, PageCtor>> = { [key in keyof T]?: InstanceType<T[key]> }

class Core<T extends Record<keyof T, PageCtor>>{
    pages: BaseCore<T> = {}
    constructor(public adapter: Adapter, pages: T) {
        Object.entries(pages).map(([key, value]) => {
            (this.pages as any)[key] = new (value as PageCtor)(adapter)
        })
    }
}

class CurrentPages {
    login = LoginPage
    logout = LogoutPage
    about = AboutPage
}


const adapter = {} as Adapter

const core = new Core(adapter, new CurrentPages())
core.pages.about;
core.pages.login;
core.pages.logon; //err
  

Комментарии:

1. похоже, это работает даже с подписью индекса в CurrentPages imgur.com/a/H5FLoor