TypeScript如何将类属性作为方法参数的配置选项类型
问题背景
现有SnackbarComponent类定义如下:
export class SnackbarComponent { optionA: number; option2: string; method1(){} }
需求是将该类的属性作为show方法options参数的键,尝试使用[I in SnackbarComponent]: SnackbarComponent[I];写法时抛出以下TS报错:
- 类型字面量中的计算属性名必须引用属于字面量类型或'unique symbol'类型的表达式。ts(1170)
- 计算属性名的类型必须为'string'、'number'、'symbol'或'any'。ts(2464)
- 找不到名称“I”。ts(2304)
- 类型“any”不能用作索引类型。ts(2538)
出错的对应代码:
export class SnackbarService { show(message: string, options?: { randomString: string; [I in SnackbarComponent]: SnackbarComponent[I]; }): Snackbar { // 创建SnackbarComponent实例 // 为SnackbarComponent实例设置属性 } }
错误原因
- 映射类型的
in遍历语法不支持直接内联写在对象类型字面量中,只能在类型别名定义中使用 - 遍历目标写法错误:要获取类实例的属性键集合,必须用
keyof 类名拿到键的联合类型,不能直接将类本身作为遍历目标 - 未处理可选性:
options是可选参数,从类中映射出的属性也应该支持按需传入,不需要全量传递 - 未做属性过滤:原类中存在
method1这类方法,默认keyof会把方法键也纳入,不符合配置项只传数据属性的常规需求
正确实现
基础版本(包含类所有属性、方法)
通过交叉类型将固定属性randomString和类映射出的属性合并,外层包Partial让所有类属性变为可选传入:
export class SnackbarService { show( message: string, options?: { randomString: string } & Partial<{ [I in keyof SnackbarComponent]: SnackbarComponent[I] }> ): Snackbar { // 创建SnackbarComponent实例 // 为SnackbarComponent实例设置属性 } }
优化版本(仅保留类的数据属性,过滤方法)
先定义工具类型过滤掉类中的函数类型属性,只保留普通数据属性作为配置项键:
// 提取类型中所有非函数属性的键 type ClassDataKeys<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] export class SnackbarService { show( message: string, options?: { randomString: string } & Partial< Pick<SnackbarComponent, ClassDataKeys<SnackbarComponent>> > ): Snackbar { // 创建SnackbarComponent实例 // 为SnackbarComponent实例设置属性 } }
这里用TS内置工具类型Pick替代手写映射,写法更简洁,效果和手写映射完全一致。如果该options类型需要多处复用,可以单独抽为类型别名,进一步提升代码可读性。
内容的提问来源于stack exchange,提问作者Get Off My Lawn
相关产品推荐
相关产品推荐

