如何使用TypeScript按条件限制类字段的访问权限
根据上下文限制TypeScript类实例的属性访问
要实现根据构造函数传入的上下文参数限制属性访问,不需要用infer,用泛型+映射/条件类型就能搞定,下面提供两种可行方案:
方案一:泛型类(保留类结构)
通过泛型绑定上下文类型,将非当前上下文的属性标记为never,访问时会触发类型警告:
type Context = 'birds' | 'mammals'; // 定义上下文与属性的映射关系 type ContextToAnimals = { birds: { chicken: string; duck: string }; mammals: { dog: string; cat: string }; }; // 生成类的类型:保留当前上下文属性,其余设为never type AnimalClass<C extends Context> = ContextToAnimals[C] & { [K in Exclude<keyof (ContextToAnimals['birds'] & ContextToAnimals['mammals']), keyof ContextToAnimals[C]>]: never; }; class MyClass<C extends Context> implements AnimalClass<C> { readonly chicken: string | never; readonly duck: string | never; readonly dog: string | never; readonly cat: string | never; constructor(context: C) { if (context === 'birds') { // 类型断言解决赋值时的类型校验问题 (this as MyClass<'birds'>).chicken = 'chicken'; (this as MyClass<'birds'>).duck = 'duck'; } else { (this as MyClass<'mammals'>).dog = 'dog'; (this as MyClass<'mammals'>).cat = 'cat'; } } } // 自动推断泛型为'birds' const myClass = new MyClass('birds'); const chicken = myClass.chicken; // ✅ 正常,类型为string const dog = myClass.dog; // ❌ 类型错误:类型为never,无法赋值
方案二:工厂函数(更简洁严格)
直接根据上下文返回不同的实例类型,非对应上下文的属性直接不存在,访问时提示属性不存在:
type Context = 'birds' | 'mammals'; // 定义不同上下文对应的实例类型 type BirdInstance = { readonly chicken: string; readonly duck: string }; type MammalInstance = { readonly dog: string; readonly cat: string }; // 条件类型根据上下文返回对应实例类型 type AnimalInstance<C extends Context> = C extends 'birds' ? BirdInstance : MammalInstance; function createMyClass<C extends Context>(context: C): AnimalInstance<C> { if (context === 'birds') { return { chicken: 'chicken', duck: 'duck' } as AnimalInstance<C>; } else { return { dog: 'dog', cat: 'cat' } as AnimalInstance<C>; } } const birdClass = createMyClass('birds'); birdClass.chicken; // ✅ 正常 birdClass.dog; // ❌ 类型错误:属性'dog'不存在于类型'BirdInstance'
关键说明
- 两种方案都不需要
infer,infer主要用于在条件类型中提取未知的类型参数,这里通过明确的泛型和映射/条件类型就能实现需求。 - 方案一更贴近你原本的类结构,方案二更简洁且类型限制更严格。
内容的提问来源于stack exchange,提问作者Stanimir Nikolov
相关产品推荐
相关产品推荐

