TypeScript 函数重载。 IDE 参数类型混淆
TypeScript function overloading. IDE argument type confusion
我正在尝试为我的 TypeScript API 获得良好的开发人员体验,但我遇到了意想不到的问题。
如下所示重载函数时:
/** Comment 1 */
function a(key: 'key1', args: { arg1: number }): string
/** Comment 2 */
function a(key: 'key2', args: { arg2: number }): string
function a(key: string, args) { }
当有人试图在 IDE 中调用该函数时(我尝试了 VSCode 和 WebStorm)
a('key2', { })
// ^
IDE 基于第二种联合建议对象 属性。 (在本例中为 arg1
和 arg2
)
我希望它的行为类似于此代码:
/** Comment 1 */
function a(key: 'key1'): (args: { arg1: number }) => string
/** Comment 2 */
function a(key: 'key2'): (args: { arg2: number }) => string
function a(key: string, args) { }
调用时在哪里
a('key2')({ })
// ^
只显示需要的属性。
是否有可能在第一种情况下得到相同的行为?
这是一个常见问题 - 例如在事件侦听器上下文中 - 我最近自己也遇到过。幸运的是,有一个简单而优雅的解决方案。
首先,在你的问题中有两种略有不同的表述方式;一次,您要正确键入的对象是 a
的另一个参数,一次是您要从 a
return 的函数的单数参数。以下解决方案应该适用于两个版本,但我将在第一种情况下展示它,这种情况应该更常见。
主要技巧是避免重载并用单个泛型替换它们;这也使得处理 a
和打字变得更加容易。据我所知,在您描述的情况下,这应该总是可行的。
第 1 步:通过接口定义函数signatures/overloads:
interface Signatures {
key1: {arg1: number};
key2: {arg2: number};
}
当然,如果参数超过2个,那就有点困难了;但是出现上述问题的典型场景通常恰好有 2 个参数 - 一个键和一个值。
步骤 2:定义单个函数泛型函数签名:
function a<K extends keyof Signatures>(key: K, args: Signatures[K]): string {
return 'hello world'; // TODO
}
然后,当您调用 a('key1',
) 时,args
会自动推断为 {arg1: number}
.
类型
我正在尝试为我的 TypeScript API 获得良好的开发人员体验,但我遇到了意想不到的问题。 如下所示重载函数时:
/** Comment 1 */
function a(key: 'key1', args: { arg1: number }): string
/** Comment 2 */
function a(key: 'key2', args: { arg2: number }): string
function a(key: string, args) { }
当有人试图在 IDE 中调用该函数时(我尝试了 VSCode 和 WebStorm)
a('key2', { })
// ^
IDE 基于第二种联合建议对象 属性。 (在本例中为 arg1
和 arg2
)
我希望它的行为类似于此代码:
/** Comment 1 */
function a(key: 'key1'): (args: { arg1: number }) => string
/** Comment 2 */
function a(key: 'key2'): (args: { arg2: number }) => string
function a(key: string, args) { }
调用时在哪里
a('key2')({ })
// ^
只显示需要的属性。
是否有可能在第一种情况下得到相同的行为?
这是一个常见问题 - 例如在事件侦听器上下文中 - 我最近自己也遇到过。幸运的是,有一个简单而优雅的解决方案。
首先,在你的问题中有两种略有不同的表述方式;一次,您要正确键入的对象是 a
的另一个参数,一次是您要从 a
return 的函数的单数参数。以下解决方案应该适用于两个版本,但我将在第一种情况下展示它,这种情况应该更常见。
主要技巧是避免重载并用单个泛型替换它们;这也使得处理 a
和打字变得更加容易。据我所知,在您描述的情况下,这应该总是可行的。
第 1 步:通过接口定义函数signatures/overloads:
interface Signatures {
key1: {arg1: number};
key2: {arg2: number};
}
当然,如果参数超过2个,那就有点困难了;但是出现上述问题的典型场景通常恰好有 2 个参数 - 一个键和一个值。
步骤 2:定义单个函数泛型函数签名:
function a<K extends keyof Signatures>(key: K, args: Signatures[K]): string {
return 'hello world'; // TODO
}
然后,当您调用 a('key1',
) 时,args
会自动推断为 {arg1: number}
.