是否可以声明一个同时适用于数字和bigints的打字稿功能? [英] Is it possible to declare a typescript function which works on both numbers and bigints?

查看:54
本文介绍了是否可以声明一个同时适用于数字和bigints的打字稿功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在普通的无类型Javascript中,编写一个可以对数字或bigint进行操作的函数并不难,具体取决于传入的参数:

In plain untyped Javascript, it's not so hard to write a function which can operate on either numbers or bigints, depending on the arguments which are passed in:

const sumOfSquares = (a,b) => a*a + b*b;
sumOfSquares(3, 4); // returns 25
sumOfSquares(3n, 4n); // returns 25n
sumOfSquares(3n, 4); // throws a TypeError

似乎应该有一种方法可以在Typescript中声明此函数,以便编译器强制将参数一起使用.我尝试过

It seems like there ought to be a way to declare this function in typescript so that the compiler will enforce that the arguments will work together. I tried

const sumOfSquares = <N extends bigint | number>(a: N, b: N): N =>
  a * a + b * b;

但是编译器拒绝:

语义错误TS2322:类型数字"不能分配给类型"N".
'number'可分配给'N'类型的约束,但是'N'可以使用约束'number |的另一子类型实例化.bigint'.

semantic error TS2322: Type 'number' is not assignable to type 'N'.
  'number' is assignable to the constraint of type 'N', but 'N' could be instantiated with a different subtype of constraint 'number | bigint'.

有没有其他方法可以编写类型声明,以便它可以正常工作?

Is there a different way to write the type declaration so that it will work?

推荐答案

以下是解决方法:

function sumOfSquares<N extends number>(a: N, b: N):N
function sumOfSquares<N extends bigint>(a: N, b: N):N
function sumOfSquares<N extends bigint | number>(a: N, b: N) {
    return a * a + b * b;
}

sumOfSquares(2n,2n) // ok
sumOfSquares(2,2) // ok
sumOfSquares(2n,2) // error
sumOfSquares(2,2n) // error

顺便说一句,您还可以为箭头功能定义重载:

Btw, you can also define overloadings for arrow function:


interface Overloading {
    <N extends number>(a: N, b: N): N
    <N extends bigint>(a: N, b: N): N
    <N extends bigint | number>(a: N, b: N): N
}

const sumOfSquares: Overloading = <N extends bigint | number>(a: N, b: N) => a * a + b * b;


sumOfSquares(2n, 2n) // ok
sumOfSquares(2, 2) // ok
sumOfSquares(2n, 2) // error
sumOfSquares(2, 2n) // error

如果将第一个参数作为简单数字传递,TS将期望第二个参数具有相同的类型.与BigInt的行为相同

If you passed first argument as simple number, TS will expect second argument to have the same type. Same behaviour with BigInt's

更新

我应该添加一种额外的泛型来使它起作用.

I should have beed add one extra generic to make it work.

感谢@jcalz向我指出正确的方向:

Thanks @jcalz for pointing me in a right direction:

function sumOfSquares<A extends number, B extends number>(a: A, b: B): number
function sumOfSquares<A extends bigint, B extends bigint>(a: A, b: B): bigint
function sumOfSquares<A extends number | bigint, B extends A>(a: A, b: B): bigint | number {
    return a * a + b * b
};

const x = 3n;
let y: number | bigint;
if (Math.random() < 0.5) y = 4;
else y = 4n;

const result = sumOfSquares(x, y) // There should be an error here
const result2 = sumOfSquares(3n, 4) // There should be an error here too
const result3 = sumOfSquares(3, 4n) // There should be an error here too
const result4 = sumOfSquares(3, 4) // ok
const result5 = sumOfSquares(3n, 4n) // ok

这篇关于是否可以声明一个同时适用于数字和bigints的打字稿功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆