TypeScript接口如何基于另一属性实现嵌套属性自动补全?
解决方案:用泛型实现动态键的自动补全
直接用普通静态接口做不到你要的效果——因为普通接口的类型是固定的,没法跟着实例后续赋值的Foo键动态更新。但可以通过泛型参数绑定Foo和Bar的键类型,不用把Test改成函数就能实现自动补全。
步骤1:定义带泛型的接口
把Foo的键类型作为泛型参数,让Bar的类型和这个泛型绑定:
// 泛型K代表Foo的键类型,默认值string兼容未设置Foo的场景 interface MyInterface<K extends string = string> { Foo?: Record<K, any>; // Record<K, any>等价于{ [key in K]: any } Bar?: Record<K, any>; }
步骤2:创建实例时让TypeScript自动推断泛型
只要在声明实例时直接初始化Foo,TypeScript会自动把Foo的键推断为泛型K的类型,Bar就能自动补全这些键:
// 初始化时直接赋值Foo,TypeScript自动推断K为"Key1" const Test: MyInterface = { Foo: { Key1: "lol" } }; Test.Bar?.Key1; // 这里会弹出Key1的自动补全提示
注意:如果要先创建空对象再赋值
如果必须先声明空对象,后续再给Foo赋值,需要通过类型断言手动更新类型,否则TypeScript无法追踪后续赋值的键:
// 先声明为带具体键的泛型类型 let Test: MyInterface<"Key1"> = {} as MyInterface<"Key1">; Test.Foo = { Key1: "lol" }; Test.Bar?.Key1; // 同样能得到自动补全
为什么普通接口不行?
普通接口的类型是静态的,一旦定义就固定了,没法感知实例运行时的赋值操作。泛型的作用是把类型参数化,让实例的类型和初始化时的Foo键绑定,从而实现动态的自动补全。
内容的提问来源于stack exchange,提问作者Peersky
相关产品推荐
相关产品推荐

