根据可选参数的类型确定返回类型

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

How to determine return type based on optional parameter's type

问题

以下是翻译好的部分:

我有以下函数:

```ts
export function safeParseInt<T>(value: any, invalid: T = undefined as T): number | T {
  if ((value ?? "") === "") return invalid;
  const parsed = parseInt(String(value));
  if (isNaN(parsed)) return invalid;
  return value ? parsed : 0;
}

在TypeScript Playground中查看

如您所见,它接受两个参数,如果能够转换,将返回第一个参数转换为整数,否则返回第二个参数。第二个参数是可选的,默认为undefined。

我在类型方面遇到了困难。如果我使用上面的版本:

function test(value: unknown) {
  const r = safeParseInt(value);
  const x: number | "" = safeParseInt(value);
  const y: number | "" = safeParseInt(value, "");
  const z: number | "" = safeParseInt(value, undefined);
}

我期望xz会出现错误,但只有z出现错误。当我悬停在r上时,我可以看到返回类型是unknown

默认值的某些地方搞乱了类型推断。我尝试过返回typeof invalid,去掉类型提示,让T扩展undefined或扩展unknown。似乎没有什么作用。


希望这对您有所帮助。

<details>
<summary>英文:</summary>

I have the following function:

```ts
export function safeParseInt&lt;T&gt;(value: any, invalid: T = undefined as T): number | T {
  if ((value ?? &quot;&quot;) === &quot;&quot;) return invalid;
  const parsed = parseInt(String(value));
  if (isNaN(parsed)) return invalid;
  return value ? parsed : 0;
}

See this in the typescript playground

As you can see it takes two parameters and returns either the first parameter converted into an integer or the second one if it is unable. The second one is optional and defaults to undefined.

I am having difficulty typing this. If I use the version above:

function test(value: unknown) {
  const r = safeParseInt(value);
  const x: number | &quot;&quot; = safeParseInt(value);
  const y: number | &quot;&quot; = safeParseInt(value, &quot;&quot;);
  const z: number | &quot;&quot; = safeParseInt(value, undefined); 
}

I expected an error on x and z, but there is only one on z. When I hover over r I can see that the return type is unknown.

Something about the default value is messing up the inference. I've tried returning typeof invalid, removing type hints altogether, making T extend undefined or making it extend unknown. Nothing seems to work.

答案1

得分: 1

根据当前函数的声明方式,如果没有提供invalid参数,它会返回一个unknown类型的结果。我在这里稍微调整了类型,使它正确。

当然,这仍然无法通过你编写的测试(后面会详细解释为什么)。但是这个函数的类型已经正确了。如果你尝试在不接受相同签名的函数中使用这个输出,编译器会警告你(在playground链接中也添加了这个)。

为什么这个函数有效呢?当你声明一个变量类型,比如const var: <type> = ...,TypeScript会使用你提供的信息来推断任何泛型类型。

因此,当你调用函数而没有提供invalid参数时,TypeScript会使用你的类型声明来“猜测”回退参数的类型必须是""类型。但当你明确传递参数时,它会使用实际参数的类型来推断泛型。

当你使用arguments时,这种推断并不会发生。这就是为什么当我尝试将它传递给一个函数时,TypeScript会抛出错误的原因。

英文:

With the way the function is currently declared it returns an unknown result if no invalid argument is provided. I've correctly the typing slightly here

Of course, this still doesn't pass the test you've written (more below on why). But this functions is typed correctly. If you try to use the outputs in a function that doesn't accept the same signature, the compiler will warn you (added this in the playground link as well)

For why this works... When you declare a type with the variable, like const var: &lt;type&gt; = ..., typescript will use what you've given to infer any generic types.

So when you call the function without the invalid argument, typescript uses your type declaration to "guess" that the fallback argument must be of type &quot;&quot;. But when you explicitly pass the argument, it uses the actual arguments type to infer the generic.

This inference doesn't happen when you use the arguments. Which is why the typescript throws an error when I try passing it to a function.

答案2

得分: 1

你应该使用重载。

export function safeParseInt(value: any): number | undefined
export function safeParseInt<T>(value: any, invalid: T): number | T
export function safeParseInt<T>(value: any, invalid: T = undefined as T): number | T {
  if ((value ?? "") === "") return invalid;
  const parsed = parseInt(String(value));
  if (isNaN(parsed)) return invalid;
  return parsed;
}

如果未向函数传递invalid参数,这将显式设置safeParseInt的返回类型为number | undefined

英文:

You should use overloads.

export function safeParseInt(value: any): number | undefined
export function safeParseInt&lt;T&gt;(value: any, invalid: T): number | T
export function safeParseInt&lt;T&gt;(value: any, invalid: T = undefined as T): number | T {
  if ((value ?? &quot;&quot;) === &quot;&quot;) return invalid;
  const parsed = parseInt(String(value));
  if (isNaN(parsed)) return invalid;
  return parsed;
}

This will explicitly set the return type of safeParseInt to number | undefined if invalid is not passed to the function.


Playground

huangapple
  • 本文由 发表于 2023年2月16日 18:20:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470817.html
匿名

发表评论

匿名网友

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

确定