TypeScript泛型类中限制构造函数键范围并让update方法仅支持构造传入键的类型实现问题
TypeScript泛型类中限制构造函数键范围并让update方法仅支持构造传入键的类型实现问题
没问题,这个需求完全可以实现!核心是通过双重泛型约束来同时限制构造函数的键只能来自指定集合,并且让update方法自动捕获构造时实际传入的键集合。
先看调整后的完整代码:
type ExampleEntries = "foo" | "bar" | "baz"; // 泛型S捕获实际传入的形状,同时约束所有键必须属于ExampleEntries class Example<S extends { [K in keyof S]: K extends ExampleEntries ? number : never }> { constructor(private values: S) {} // update的key只能是构造时实际传入的键,value类型对应S中该键的类型(这里固定是number) update<K extends keyof S>(key: K, value: S[K]) { this.values[key] = value; } } // ✅ 合法:仅传入ExampleEntries内的键 const example = new Example({ foo: 0, bar: 1 }); // ❌ 报错:"fuz"不在ExampleEntries中,对应的类型是never,无法赋值为2 const errorExample = new Example({ foo: 0, bar: 1, fuz: 2 }); // ✅ 合法:"foo"是构造时传入的键 example.update("foo", 2); // ❌ 报错:"baz"未在构造时传入,不属于keyof typeof example.values example.update("baz", 2);
关键逻辑解释
- 泛型
S的约束{ [K in keyof S]: K extends ExampleEntries ? number : never }:确保传入的对象中,所有键都必须是ExampleEntries的成员。如果出现不在集合内的键(比如fuz),该键对应的类型会被推断为never,而never类型无法赋值为具体数值,从而触发TypeScript报错,达到禁止额外键的目的。 update方法使用泛型K extends keyof S:让TypeScript自动推导key的范围只能是构造时实际传入的键集合,完美满足你“只能更新已传入键”的需求。
更直观的替代写法
如果你希望约束逻辑更直白,也可以用下面的写法,效果完全一致:
class Example<S extends Partial<Record<ExampleEntries, number>>> { constructor(private values: S) {} update<K extends keyof S>(key: K, value: S[K]) { this.values[key] = value; } }
这里Partial<Record<ExampleEntries, number>>表示“ExampleEntries中任意子集的键,对应值为number”,同样能禁止额外键的传入,同时保留实际传入键的类型信息。
两种写法都能实现你的需求,选哪种看你觉得哪种更易读~
内容来源于stack exchange
相关产品推荐
相关产品推荐

