如何使用索引类型的intellisense维护属性访问

时间:2019-02-01 11:41:46

标签: typescript

让我们说我有一个接口“ 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

如果索引类型中有更多属性,还有一个优点是可以同时使用两个类的属性。

谢谢您的回答!

1 个答案:

答案 0 :(得分:0)

仅当您不介意额外的函数调用时才可以这样做。变量不能同时被限制在一个接口上,而是让编译器推断出对象文字的实际类型。

您可以使用具有受约束的通用类型参数的函数来完成此操作,但该参数将根据传入的实际参数来推断:

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