我可以使用模板字符串类型来自动推断 TypeScript 中 globalThis 键的类型吗?

问题描述 投票:0回答:1

在我的 Three.js 调试工作流程中,为了方便起见,我经常将对象附加到

globalThis
。然而,随着 globalThis 对象变得越来越大,手动声明每个属性的类型变得乏味。

我想知道 TypeScript 是否可以自动推断以特定字符串结尾的键的类型,例如

Material

例如,我希望

globalThis
上以 Material 结尾的所有属性(即与模板字符串类型
${string}Material
匹配的键)被视为 THREE.MeshPhysicalMaterial。

declare global {
    var camera: THREE.PerspectiveCamera
    var scene: THREE.Scene
    var renderer: THREE.WebGLRenderer
    var setCameraToLeft: () => void
    var setCameraToRight: () => void
    var bigBoxMaterial: THREE.MeshPhysicalMaterial
    var middleBoxMaterial: THREE.MeshPhysicalMaterial
    var smallBoxMaterial: THREE.MeshPhysicalMaterial
    ...Material: THREE.MeshPhysicalMaterial
}

或许是类似这样的定义...

declare global {
    var camera: THREE.PerspectiveCamera
    var scene: THREE.Scene
    var renderer: THREE.WebGLRenderer
    var setCameraToLeft: () => void
    var setCameraToRight: () => void
    [key: string]: key extends `${string}Material` ? THREE.MeshPhysicalMaterial : unknown
}
typescript
1个回答
0
投票

看起来您想将索引签名合并

typeof globalThis
中。不幸的是,这是不可能的; microsoft/TypeScript#57353 有一个功能请求,但参与度并不高,所以我怀疑我们很快就会看到这一点。

我能想象到的最接近的方法是将索引签名合并到与全局对象相对应的接口中,例如 DOM 中的 Window

 接口
:

declare global { interface Window { [k: `${string}Material`]: THREE.MeshPhysicalMaterial } }
这是使用 

模板字符串模式索引签名 来表示每个以 Material

 结尾的键都将具有 
THREE.MeshPhysicalMaterial
 类型的属性(这不太可能是真的,对吧?也许您想要 
| undefined
 在那里)或者也许你想使用 
--noUncheckedIndexedAccess

然后您可以索引到

window

(但不能索引到 
globalThis
 或使用全局变量)来访问内容:

window.randomMaterial.alphaHash; // okay
您也可以

可能重新声明globalThis

喜欢

declare let globalThis: Window
然后

globalThis.randomMaterial.alphaHash

就可以工作,但这变得更加脆弱。

所以你可以比放弃更接近你的目标,但我不知道这是否值得付出努力。从某种意义上说,这并不比仅仅在引用

globalThis 的变量上使用 类型断言

 更好,而不是试图真正搞乱合并:

const myGlobal = globalThis as typeof globalThis & { [k: `${string}Material`]: THREE.MeshPhysicalMaterial }; myGlobal.randomMaterial.alphaHash; // okay

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.