我有一个通用接口,在该接口中,我希望一个属性仅包含来自另一个属性的键,并且具有相同的类型。...
interface IMyInterface<T> {
propA: T;
propB: { [key in keyof T]?: T[key] };
}
这很好,我之前做过很多次类似的事情。...基本上,我希望它根据传递给propA的内容来推断T是什么。
但是,这是我的问题,我有一本字典,其中包含许多IMyInterface类型。...
interface IMyDictionary {
[key: string]: IMyInterface;
}
这是我的问题所在,上面的定义需要一个泛型类型。...但是我使用的任何类型都将应用于每个属性。如果我使用除此以外的任何东西,这都是不对的,因为在声明我的字典时,它假定一切都是任意的。
interface IInterfaceA {
name: string;
age: number;
}
const objA: IInterfaceA = {
name: 'John',
age: 18
}
const myDictionary: IMyDictionary {
test1: {
propA: objA,
propB: { age: 40 }
}
}
因此,基本上,当将值分配给上述myDictionary时,我希望它推断propA为IInterfaceA类型,并且在propB中仅允许使用字符串类型的属性名称和使用数字类型的age。
通过不定义类型IMyDictionary,然后逐个创建每个项目,然后将它们分配给新对象(myDictionary),我可以轻松地做到这一点。
const test1: IMyInterface = {
propA: objA,
propB: { age: 40 }
}
const myDictionary = { test1 }
这将推断test1的通用类型,然后使用确切的属性名称而不是字符串数组来推断myDictionary的类型。但是如果可能的话,我宁愿使用普通的旧对象分配语法。
我想不出一种方法来声明IMyDictionary的类型,以强制它为每个IMyInterface实例推断通用类型。另外,我对定义IMyInterface来推断propB的属性和类型的不同方法持开放态度。
谢谢!
答案 0 :(得分:2)
您要查找的类型是字典,其中每个条目都是 some IMyInterface<T>
类型,但没有任何 specific T
类型。最好用{[k: string]: IMyInterface<exists T>}
之类的existential type来表示,目前TypeScript(其他大多数带有泛型的语言)都不支持本机。 TypeScript(以及大多数其他具有泛型的语言)仅具有 universal 类型:想要一个X<T>
类型的值的人可以为他们想要的T
指定任何类型,并且提供程序价值必须能够遵守。存在类型则相反:有人想要提供诸如X<exists T>
之类的类型的值,可以为他们想要的T
选择任何特定类型,而该值的接收者只需遵守即可。现有类型使您可以“隐藏”非通用类型内部的通用类型。
但是,TypeScript没有存在性类型,因此我们将不得不做其他事情。 (嗯,它没有 native 存在类型。您可以通过使用泛型函数并通过回调反转控制来emulate them,但使用起来比我要解决的方案还要复杂。提出下一步建议。如果您仍然对存在性感兴趣,可以阅读有关它的链接文章。
我们要做的第二件事是将IMyDictionary
的形状描述为通用类型,而我们实际上并不关心它,并让编译器尽可能地为我们推断它。这是一种方法:
type IMyDictionary<T> = { [K in keyof T]: IMyInterface<T[K]> }
const asIMyDictionary = <T>(d: IMyDictionary<T>) => d;
这个想法是,您可以使用辅助函数IMyDictionary
来获取值并生成合适的类型asIMyDictionary()
,而不是将变量声明为IMyDictionary<T>
类型。顺便说一下,这仅起作用,因为类型IMyDictionary<T>
是homomorphic mapped type,所以可以从类型T
的值推断出IMyDictionary<T>
。让我们看看它的作用:
const myDictionary = asIMyDictionary({
test1: {
propA: { name: "John", age: 18 },
propB: { age: 40 }
},
test2: {
propA: { size: 10, color: "blue" },
propB: { color: "purple" }
},
test3: {
propA: { problem: true },
propB: { oops: false } // error!
// ~~~~~~~~~~~~
// 'oops' does not exist in type '{ problem?: boolean | undefined; }'
}
});
这可以正常工作,并在您期望的地方给您错误。是的!
这里需要说明的是,您仍然需要拖延不需要的T
类型。您希望仅处理具体IMyDictionary
的任何函数或类型都必须成为通用的。也许这对您来说不是很痛苦。如果是这样,则可以考虑“模拟”的存在类型。但是我已经在这里写了很多东西,因此希望以上内容对您有帮助...如果您需要我写出模拟的存在版本,则可以。
祝你好运!