Машинопись: Как преобразовать строку в тип - PullRequest
0 голосов
/ 10 января 2019

Я создаю несколько веб-компонентов, и каждый из них может генерировать пользовательские события. В качестве примера приведем два простых примера:

//MyButton
emits 'myButtonPressed' and detail of this type:
interface ButtonDetailType {
  id: string;
}

//MySlider
emits 'mySliderChanging' and details of this type:
interface SliderChangingDetailType {
  id: string;
  value: number;
}
emits 'mySliderChanged' and details of this type:
interface SliderChangedDetailType {
  id: string;
  oldValue: number;
  newValue: number;
}

Для прослушивания компонентов у меня есть код, который выглядит следующим образом:

buttonEl.addEventListener( 'myButtonPressed', ( event : CustomEvent ) => {
  const detail = event.detail as ButtonDetailType;
  //now i have access to detail.id
} );

sliderEl.addEventListener( 'mySliderChanging', ( event : CustomEvent ) => {
  const detail = event.detail as SliderChangingDetailType;
  //now i have access to detail.id, detail.value
} );

Поскольку я делаю больше компонентов, у меня возникают трудности с запоминанием всех пользовательских имен событий, которые может испускать каждый компонент, или detailType, который генерирует каждое событие.

Чтобы решить эту проблему, я надеялся создать объект, содержащий всю информацию, подобную этой:

EVENTS = {
  button: {
    myButtonPressed: 'myButtonPressed',
    detailType: 'ButtonDetailType',
  },
  slider: {
    mySliderChanged': 'mySliderChanged',
    detailTypes: {
     'SliderChangedDetailType',
     'SliderChangingDetailType',
    }
  }
};

Теперь у меня есть простой способ получить доступ ко всем именам событий, доступных для каждого компонента, с автозаполнением, помогающим мне в процессе ввода:

buttonEl.addEventListener( EVENTS.button. //autocomplete shows me all event names here! YAY!
sliderEl.addEventListener( EVENTS.slider. //autocomplete here too!

У меня проблема в том, что я не знаю, как преобразовать строку в тип . Я хотел бы иметь возможность напечатать это:

buttonEl.addEventListener( EVENTS.button.myButtonPressed, ( event : CustomEvent ) => {
  const detail = event.detail as EVENTS.button.detailType; // <- invalid: EVENTS.button.detailType is a string not a type!
} );

Есть ли способ преобразования строк в типы в TypeScript?

1 Ответ

0 голосов
/ 10 января 2019

Вы не можете конвертировать строки в типы без отображения. Фактически, вы действительно не хотите, чтобы эти строки были первыми, за исключением фактической строки, переданной в addEventListener() в качестве параметра type. Похоже, что вам действительно нужно что-то вроде пространства имен или модуля для организации ваших типов.

Например, используя пространства имен, мы можем получить нечто похожее на ваш EVENTS объект, за исключением того, что вместо ссылки только на строковые значения, он ссылается на строковые значения и типы:

namespace EVENTS {
  export namespace button {
    export const myButtonPressed = "myButtonPressed";
    export namespace detailType {
      export interface ButtonDetailType {
        id: string;
      }
    }
  }
  export namespace slider {
    export const mySliderChanged = "mySliderChanged";
    export namespace detailTypes {
      export interface SliderChangingDetailType {
        id: string;
        value: number;
      }
      export interface SliderChangedDetailType {
        id: string;
        oldValue: number;
        newValue: number;
      }
    }
  }
}

Это должно дать вам те же автозаполнения, которые вы видели ранее, плюс те для типов:

buttonEl.addEventListener(EVENTS.button.myButtonPressed, ((event: CustomEvent) => {
  const detail = event.detail as EVENTS.button.detailType.ButtonDetailType;
}) as EventListener);

sliderEl.addEventListener(EVENTS.slider.mySliderChanged, ((event: CustomEvent) => {
  const detail = event.detail as EVENTS.slider.detailTypes.SliderChangedDetailType;
}) as EventListener)

Вам решать, хотите ли вы изменить уровень вложенности и именования вещей, поскольку пространство имен делает некоторые вещи избыточными (может быть, вы хотите EVENTS.slider.details.SliderChanged вместо EVENTS.slider.detail<b>Type</b>s.SliderChanged<b>DetailType</b>), но основная идея здесь заключается в общем подходе использования пространств имен или модулей.

Надеюсь, это поможет; удачи!

...