TypeScript中为对象数组分配联合类型值时,如何设计setState函数?
类型安全的setState函数实现方案
你当前的setState函数存在类型不匹配风险:因为value被定义为boolean | string的联合类型,导致可以给IsRunning传入字符串、给Name传入布尔值,TypeScript无法拦截这类不符合PersonState定义的错误。
要解决这个问题,我们可以通过泛型建立key与对应value的类型关联,让TypeScript自动校验参数的合法性:
enum SomeStateEnum { IsRunning, Name, } type PersonState = { [SomeStateEnum.IsRunning]: boolean; [SomeStateEnum.Name]: string; }; const state: PersonState = { [SomeStateEnum.IsRunning]: false, [SomeStateEnum.Name]: 'John Doe', }; // 泛型约束实现类型安全的setState function setState<K extends SomeStateEnum>(key: K, value: PersonState[K]) { state[key] = value; } // 合法调用:类型完全匹配 setState(SomeStateEnum.IsRunning, true); setState(SomeStateEnum.Name, "Jane Smith"); // 非法调用:TypeScript直接抛出类型错误 setState(SomeStateEnum.IsRunning, "invalid"); // 错误:"string"不能赋值给"boolean" setState(SomeStateEnum.Name, false); // 错误:"boolean"不能赋值给"string"
核心原理
- 泛型
K被约束为SomeStateEnum的成员,确保传入的key只能是枚举中定义的有效值 value的类型绑定为PersonState[K],也就是PersonState中对应key的属性类型,彻底建立了key与value的类型关联- 调用函数时,TypeScript会根据传入的
key自动推断value的合法类型,一旦不匹配就会立即报错,完全保证类型安全
如果偏好函数重载的写法,也可以这样实现:
// 重载声明:明确每个key对应的value类型 function setState(key: SomeStateEnum.IsRunning, value: boolean): void; function setState(key: SomeStateEnum.Name, value: string): void; // 实现函数 function setState(key: SomeStateEnum, value: boolean | string) { state[key] = value; }
不过泛型写法更简洁,当枚举或状态类型新增成员时,不需要逐个补充重载声明。
内容的提问来源于stack exchange,提问作者Pål Thingbø
相关产品推荐
相关产品推荐

