Typescript:如何将字符串转换为类型

12

我正在创建一堆 Web 组件,每个组件都可以发出自定义事件。举个例子,以下是两个简单的示例:

//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
} );

随着我创建更多的组件,我很难记住每个组件可以发射的自定义事件名称或每个事件生成的详细类型。

为了解决这个问题,我希望创建一个包含所有信息的对象,就像这样:

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个回答

8
没有映射,您无法真正将字符串转换为类型。实际上,除了作为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),但主要思想是使用命名空间或模块的一般方法。

希望这有所帮助,祝你好运!


太棒了,这正是我正在寻找的! - Marek Krzeminski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接