Машинопись: Как преобразовать строку в тип
Я создаю кучу веб-компонентов, и каждый из них может генерировать пользовательские события. В качестве примера приведем два простых примера:
//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 ответ
Вы не можете действительно преобразовать строки в типы без отображения. На самом деле, вы действительно не хотите, чтобы эти строки были первыми, за исключением фактической строки, переданной в 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.detailTypes.SliderChangedDetailType
), но основная идея здесь - общий подход к использованию пространств имен или модулей.
Надеюсь, это поможет; удачи!