【问题标题】:Inline a type definition in TypeScript在 TypeScript 中内联类型定义
【发布时间】:2021-01-31 19:23:59
【问题描述】:

我正在为一个没有类型定义的 jQuery 库编写类型定义文件 (index.d.ts)。
该库的方法重复接受相同多类型(string | number | [])的参数,因此我将其定义为CustomType

export type CustomType = string | number | [];

declare global {
    interface JQuery<TElement = HTMLElement> {
        setFoo(foo: CustomType): this;
        setBar(bar: CustomType): this;
    }
}

当我现在想在 jQuery 对象上调用 setFoo() 时,(IntelliJ 的)类型提示显示参数 foo: CustomType 是预期的,如果不查找该类型的相似之处,它不会帮助其他开发人员。
相反,我希望看到提示显示 foo: string | number | [] 的类型。

例如,在 C++ 中有一个 inline 函数的概念,它基本上告诉编译器将内联函数体的代码直接放入调用它的块中,而不是调用/跳转到函数。 TypeScript 中有类似的东西吗?

如何强制 TypeScript 内联此 CustomType 并使其显示为 foo: string | number | [] 而不是 foo: CustomType

丑陋的解决方案

declare global {
    interface JQuery<TElement = HTMLElement> {
        setFoo(foo: string | number | []): this;
        setBar(bar: string | number | []): this;
    }
}

一种解决方案是消除 CustomType 并使用它们的多类型显式类型参数,但是随着越来越多的方法使用相同类型,这变得相当不方便,因为它没有从可重用性中受益,而且看起来对我来说很丑。

想象的解决方案

export type CustomType = string | number | [];

declare global {
    interface JQuery<TElement = HTMLElement> {
        setFoo(foo: inline CustomType): this; // <-- note the 'inline' here
        setBar(bar: inline CustomType): this;
    }
}

这将是理想的,并且在我的想象中表现得像“丑陋的解决方案”,但不幸的是不支持。那么实现这一目标的正确方法是什么?

【问题讨论】:

  • 请注意,[] 类型是一个长度为零的元组,而不是像 any[]Array&lt;any&gt; 这样的任意数组。那是你真正想要的类型吗?
  • string | number | [] 很简单,在我看来,我能想到的任何东西都更丑陋。比如,this 是你想要使用的东西吗?
  • 由于我现在无法测试它,出于好奇,如果不导出 CustomType 会怎样?这有什么改变吗?
  • @jcalz 感谢有关[] 的提示。我的意思是使用any[]。我会考虑您声明const 然后使用typeof 使类型有点hacky 的方法,但是鉴于该CustomType 在该库中的很多地方使用,我仍然愿意为了可重用性和维护性,接受您的代码 sn-p 作为有效答案。
  • @IngoBürk 不导出 CustomType 在这方面没有任何改变。据我了解,export 只允许使用importexport 你所有的类型和接口似乎是一个好习惯。

标签: typescript inline type-definition


【解决方案1】:

我认为目前这是不可能的。

有一个开放的 GitHub 问题 microsoft/TypeScript#25784,要求能够“深入”到 IntelliSense 快速信息,如果实施,可能会或可能不会将工会扩展到其成员。

还有microsoft/TypeScript#40780 要求使用与您建议的类似的“别名”关键字:基本上是一个类型宏,在任何使用代码的人查看它时都会被消除.此问题已作为看起来略有不同的功能的草稿拉取请求的副本而关闭。所以这方面的研究似乎很快就消失了。


因此,解决方法:创建/声明您想要内联的类型的变量 x,并将此类型称为 typeof x。我相信,在呼叫站点,IntelliSense 应该将typeof x 解析为扩展类型。我不能保证这总是会发生(编译器如何决定呈现类型信息的细节对我来说有点模糊),但它似乎在我的测试中做到了这一点。例如:

const __Custom: string | number | any[];

interface JQuery<TElement = HTMLElement> {
  setFoo(foo: typeof __Custom): this;
  setBar(bar: typeof __Custom): this;
}

然后:

declare const $: JQuery;
$.setBar(""); // IntelliSense says 
// setBar(bar: string | number | any[]): JQuery<HTMLElement>

这可能适合你,也可能不适合你。

Playground link to code

【讨论】:

    猜你喜欢
    • 2020-07-31
    • 1970-01-01
    • 2017-09-18
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 2021-02-27
    • 2018-12-03
    • 2019-02-04
    相关资源
    最近更新 更多