首页 > 解决方案 > 如何在索引类型中使用智能感知维护属性访问

问题描述

假设我有一个接口“IndexedInterface”,它应该只有描述来保存另一个接口类型“PropertyInterface”的属性。

我用它来定义一个具有“IndexInterface”接口类型的对象。这很好用,因为代码完成将为我提供我添加的每个属性的“PropertyInterface”信息。

到目前为止没有问题。

但是现在我想从此对象访问一个属性,而打字稿编译器无法解析之前定义的属性名称。

现在的问题是:目前打字稿中是否有一种方法可以实现索引类型与对象声明中的派生类型的组合?

提前致谢。

interface PropertyInterface 
   someProp: string;
}

interface IndexedInterface {
  [key: string]: PropertyInterface;
}

const testObj: IndexedInterface = {
 prop1: {
   someProp: 'test'
 }
};

testObj. // here the intellisense should tell me that 'prop1' is available

编辑:

感谢 Titian Cernicova-Dragomir,我找到了一种使用类的动态方法:

class TypeMerger<T> {
    mergeTypes<U>(o: T): T & U {
        return o as T & U;
    }
}

const testObj = new TypeMerger<IndexedInterface>.mergeTypes({
 prop1: {
   someProp: 'test'
 }
});

testObj.prop1 // works like a charm now from intellisense

如果索引类型中有更多属性,那么这两个类的属性也都可用。

谢谢你的回答!

标签: typescript

解决方案


如果您不介意额外的函数调用,您只能这样做。变量不能同时被约束到一个接口,而是让编译器推断出对象字面量的实际类型。

您可以使用具有受约束但将根据传入的实际参数推断的泛型类型参数的函数来执行此操作:

interface PropertyInterface {
  someProp: string;
}


interface IndexedInterface {
  [key: string]: PropertyInterface;
}

function createIndexedInterface<T extends IndexedInterface>(o: T) {
  return o;
}

const testObj = createIndexedInterface({
  prop1: {
    someProp: 'test'
  }
});

testObj.prop1.someProp // ok 

你可以创建一个更通用的函数版本,使用一个返回函数的函数(你的类解决方案也是一个很好的,添加这个是为了完整性)

function createIndexedInterface<T>() {
  return function <U extends T>(o: U) {
    return o;
  }
}
const testObj = createIndexedInterface<IndexedInterface>()({
  prop1: {
    someProp: 'test'
  }
});

testObj.prop1.someProp // ok

推荐阅读