在我的 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
}
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