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