typescript - 打字稿:只键入对象值并让打字稿键入键
问题描述
我有一个像
interface PageDef = {url: string}
const page1Def: PageDef = {url: "page1"}
const page2Def: PageDef = {url: "page2"}
const pages = {page1: page1Def, page2: page2Def}
现在我希望页面类型如下:
{{page1: PageDef, page2: PageDef}}
问题是该页面可以有任何名称,例如我可以有
const pages = {home: page1Def, about: page2Def}
我不想使用以下任何一种,因为我会松开类型中的键
const pages: {[pageName: string]: PageDef} = {page1: page1Def, page2: page2Def}
const pages: Record<string, PageDef> = {page1: page1Def, page2: page2Def}
我无法执行以下操作来获得联合类型的页面名称
keyof typeof pages
// would be string with above definition
不键入会使 Typescript 动态键入pages
,这将部分解决我的问题,但会键入检查值。
所以我的问题是,是否可以仅手动键入对象的值?或者有没有其他解决方案?
解决方案
为什么首先明确定义“页面”的类型?在这种情况下它似乎没有用。
定义类型的原因是您可以在多个文件、函数或其他任何内容中重复使用它。但是没有办法做到这一点,同时保持“页面”的键在所有用法中静态知道,它必须是string
. 或者,您可以通过为其定义联合类型来使其静态已知(如在另一个答案中提到的type pageNames = 'page1' | 'page2' | 'home' | 'about'
)。
比如,你明确输入“页面”的用例是什么?如果您想将该值传递给函数,则无论如何都只需使用泛型,“页面”的确切键将无关紧要:
function doSomething<MyType extends {[key: string]: PageDef}>(pageObj: MyType) {}
即使这样,它也只有在返回fromdoSomething()
是通过泛型从其推断使用中以某种方式有用地键入,或者您在函数上有其他通过泛型有用地通知的参数时才有用。否则,函数体可能实际上并不关心pageObj
.
明确知道“页面”的键是什么可能有用的唯一地方将是在它定义的相同范围内。在这种情况下,你可以让 TypeScript 推断它的键值,这将是实际的键而不是string
:
interface PageDef = {url: string}
const page1Def: PageDef = {url: "page1"}
const page2Def: PageDef = {url: "page2"}
const pages = {page1: page1Def, page2: page2Def}
type PagesKeys = keyof typeof pages; // "page1" | "page2"
但又一次,你为什么要打扰?您的要求与您实际需要的内容有点模糊。它可能看起来很有用,但我怀疑它实际上是否有用。或者,如果是,它似乎是一种设计反模式,您需要重新考虑设计中的其他一些高级事物。
推荐阅读
- python - LiveSearch Flask 和 Ajax 返回 undefined
- python - 如何在odoo中强制删除行中的记录?
- r - 如何对数据框列表中的每个数据框应用相同的过滤器
- reactjs - reducer 返回 null(用路由器和参数反应 redux)
- javascript - lit-element 和 lit-html 有什么区别?
- python - 通过 jupyter_client API 优雅地中断 jupyter 内核
- numpy - 在 Numpy 中更改数组的形状
- python - 应用函数并使用装饰器检查自定义异常
- python - 带有 OpenCV 的视频叠加系统
- python - python 中的 Str.replace 似乎不起作用