TypeScript:如何仅在其他文件定义类型时导入该类型
在自动生成的Preact类型文件中,根据Web组件是否导出指定类型做条件类型定义
我有一批Web组件文件,部分文件会导出一个可选类型(实际是自定义事件event.detail的类型接口,简称OptionalType)。另外有一批自动生成的文件,每个对应一个Web组件,用来提供该组件的Preact类型。现在需要在这些自动生成的文件里,根据原Web组件文件是否导出OptionalType,来条件定义部分类型。
组件文件示例
部分Web组件文件会包含如下导出:
export interface OptionalType { name: string }
最初尝试的问题
我一开始尝试用import * as all导入整个模块,再通过typeof all判断是否存在OptionalType,写法如下:
import * as all from "./my-component" type OptionalType = typeof all extends { OptionalType: unknown } ? typeof all["OptionalType"] : never // 使用OptionalType
但这种写法不生效——在JavaScript中all是包含所有导出的对象,但在TypeScript里,typeof all得到的是模块的命名空间类型,无法通过这种方式判断导出类型是否存在。不过内联定义测试时逻辑是正常的:
interface All { OptionalType: { name: string } } type OptionalTypeInline = All extends { OptionalType: unknown } ? All["OptionalType"] : never // 使用OptionalType
正确的实现方式
要正确判断模块是否导出指定类型,应该直接针对模块的导出类型集合做键检查,结合import type来实现:
import type * as all from "./my-component" type OptionalType = 'OptionalType' extends keyof all ? all['OptionalType'] : never
这种写法直接验证OptionalType是否属于模块导出类型的键,能正确推导对应的类型,不存在时则返回never。
实际场景的最终方案
后来我发现实际场景是处理CustomEvents,通过重构代码解决了问题,最终调整为如下写法:
[K in keyof Events]: ( e: Events[K] extends keyof all.CustomEvents ? TargetedEvent<Component> & { detail: all.CustomEvents[Events[K]] } : TargetedEvent<Component> ) => void
内容的提问来源于stack exchange,提问作者Tigran
相关产品推荐
相关产品推荐

