如何在 TypeScript 中声明实验性全局变量?

huangapple go评论73阅读模式
英文:

How to declare experimental global variables in TypeScript?

问题

需要在运行时检查浏览器是否支持EyeDropper API。以下是 TypeScript 代码示例:

// 用于检查EyeDropper API是否可用的类型
type EyeDropperCheck = typeof EyeDropper | undefined;

// 运行时检查
if (typeof window.EyeDropper === "function") {
    const eyeDropper: EyeDropperCheck = window.EyeDropper;
    // EyeDropper 可用,可以安全地使用
} else {
    const eyeDropper: EyeDropperCheck = undefined;
    // EyeDropper 不可用
}

// 现在您可以使用 eyeDropper 变量,它要么是 EyeDropper 类型,要么是 undefined

这段代码首先定义了一个名为 EyeDropperCheck 的类型,用于检查 EyeDropper 是否可用。然后,在运行时,它通过 typeof window.EyeDropper 来检查 EyeDropper 是否是一个函数,如果是函数,就表示它可用,然后将其分配给 eyeDropper 变量,否则将 undefined 分配给 eyeDropper 变量。这样,您可以根据 eyeDropper 变量的类型来安全地使用 EyeDropper API 或处理它不可用的情况。

英文:

I need to use the EyeDropper API in my TypeScript project. TypeScript compiler doesn't know anything about this API, so I declared it myself:

interface ColorSelectionResult {
    sRGBHex: string;
}

interface ColorSelectionOptions {
    signal: AbortSignal;
}

declare class EyeDropper {
    open(options?: ColorSelectionOptions): Promise<ColorSelectionResult>;
}

export default EyeDropper;

It works great, however I'm not sure how to properly check if this API is handled by the browser in the runtime:

if (typeof EyeDropper === "function") {
    // EyeDropper is available
}

This would work, but I'd need to remember about the check. Instead, I'd prefer the TypeScript engine remember that it's either a class, or undefined. I tried to create a type:

type EyeDropper = EyeDropperClass | undefined;

export default EyeDropper;

But then, I can't use this type to explicitly check if EyeDropper is available. I tried this:

if (window.EyeDropper === "function") {
    // Property 'EyeDropper' does not exist
    // on type 'Window & typeof globalThis'.ts(2339)
}

Instead, this would work:

if ("EyeDropper" in window) {
    // EyeDropper is available
}

But this time, it's a little hacky and I'd prefer to do the check via type, not string.

How should it be done in TypeScript?

答案1

得分: 1

在TypeScript中,typeof运算符用于值 - 实际上并不是用于类型。

最佳方法是使用类型扩展来向Window接口添加新属性。这意味着该属性的类型可以是EyeDropperundefined,这意味着该API可能存在也可能不存在。

在全局类型定义文件(通常命名为globals.d.ts)中,您可以添加:

declare global {
    interface Window {
        EyeDropper?: EyeDropper;
    }
}

在您的实际代码中,您可以使用一个类型守卫函数来检查EyeDropper API是否存在:

function isEyeDropperAvailable(): window.EyeDropper is EyeDropper {
    return typeof window.EyeDropper === "function";
}

if (isEyeDropperAvailable()) {
    // EyeDropper可用
}
英文:

In Typescript, typeof operator is used for values - not really meant for types.

The best way of going about this is to use type augmentation to add new property to the Window interface. This means that the property would have the type of EyeDropper or undefined, meaning that the API may or may not exist.

In the global type definition file (typically named globals.d.ts), you can add:

declare global {
    interface Window {
        EyeDropper?: EyeDropper;
    }
}

With your actual code, you can use a type-guard function to check if the EyeDropper API exists:

function isEyeDropperAvailable(): window.EyeDropper is EyeDropper {
    return typeof window.EyeDropper === "function";
}

if (isEyeDropperAvailable()) {
    // EyeDropper is available
}

huangapple
  • 本文由 发表于 2023年7月14日 00:19:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76681480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定