我有一个像这样的功能:
function getBlogs(limit?: number) { ... }
将limit
只能是一个正整数,它不能是0
。
我怎么告诉打字稿这个数字只能大于0?
有一个公开的建议microsoft / TypeScript#15480支持“范围类型”,在这里您可以说一些类似的东西type PositiveWholeNumbers = 1..9999999
来表示您的类型。还有一个(封闭的)建议microsoft / TypeScript#4639支持int
和uint
-like类型,在这里也可能起作用。遗憾的是,这两种方法都没有实现,因此,如果要在类型系统中进行此操作,则需要做其他事情。
如果(在千有一个相当小的上限最多),您可以手动生成一个工会的容许值以及在库文件中的某个地方推它。可以以编程方式完成此操作,因此您无需进行物理输入,但与您输入的内容相同:
// Evaluate the following in JS and copy into your code somewhere
// "type AllowableValues = "+
// Array.from({length: 5000}, (x, i) => String(i+1)+((i+1)%100?"":"\n")).join(" | ")+";";
// which produces:
type AllowableValues = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | // and so on
function getBlogs(limit?: AllowableValues) {
console.log((limit || 0).toFixed());
}
从某种意义上说,这将起作用,编译器将limit
在并集(或undefined
)中看到某个数字值,并且getBlogs()
将针对该数字值调用进行验证:
getBlogs(100); // okay
getBlogs(1); // okay
getBlogs(1.5); // error!
// ----> ~~~
// Argument of type '1.5' is not assignable to
// parameter of type 1 | 2 | 3 | ...
getBlogs(0); // error!
// ----> ~
// Argument of type '0' is not assignable to
// parameter of type 1 | 2 | 3 | ...
getBlogs(-4);
// ----> ~~
// Argument of type '-4' is not assignable to
// parameter of type 1 | 2 | 3 | ...
当然,超出范围的任何操作都会失败:
getBlogs(1234567); // error (too big)
getBlogs(1e100); // error (too big)
这仅在人们getBlogs()
使用某些数字文字进行调用时才有效。数学运算容易产生number
,其范围太广而无法验证:
getBlogs(3+1); // error: safe but the compiler can't tell
另外我还注意到,像上面这样的大型联合会陷入困境,足以使我的IDE呆滞,所以我真的只建议对多达数百个数字进行此操作。
另一种可能性是制作getBlogs()
一个泛型函数,其中对参数进行验证以确保其为正整数。我认为,您可以使用模板文字类型在TypeScript 4.1中完成此操作:
type AsPositiveWholeNumber<N extends number> =
N extends 0 ? PositiveWholeNumber :
number extends N ? PositiveWholeNumber :
`${N}` extends `${infer F}${"." | "-"}${infer L}` ?
PositiveWholeNumber : N
type PositiveWholeNumber = {
["Please choose a value that is a positive whole number"]: number
} & number
function getBlogs<N extends number>(limit?: AsPositiveWholeNumber<N>) {
console.log((limit || 0).toFixed());
}
在此,该getBlogs()
函数接受limit
type的参数AsPositiveWholeNumber<N>
,其中N
是一个number
由limit
传入值推断的-约束类型参数。AsPositiveWholeNumber<N>
设计该类型的目的是,如果N
是正整数,AsPositiveWholeNumber<N>
则将为N
。否则,它将是PositiveWholeNumber
伪类型,其目的是向用户提供看似有用的错误消息。
重要的工作在内部完成AsPositiveWholeNumber<N>
。首先,我们确保N
既不是也不number
是0
。然后,我们通过模板文字类型将其转换为字符串`${N}`
,然后确保此字符串版本N
包含no"."
或"-"
字符。这至少应该将正整数与其他数字区分开,至少直到我们得到一个巨大的值,该值是整数,但其字符串表示形式以小数点形式表示(例如1.23456789e+23
)。
让我们看看它是否有效:
getBlogs(100); // okay
getBlogs(1); // okay
getBlogs(1.5); // error!
// ----> ~~~
// Argument of type '1.5' is not assignable to
// parameter of type 'PositiveWholeNumber | undefined'
getBlogs(0); // error!
// ----> ~
// Argument of type '0' is not assignable to
// parameter of type 'PositiveWholeNumber | undefined'
getBlogs(-4);
// ----> ~~
// Argument of type '-4' is not assignable to
// parameter of type 'PositiveWholeNumber | undefined'
getBlogs(1234567); // okay
getBlogs(1e100); // okay, but
getBlogs(11e98); // error: becomes 1.1e+99
getBlogs(3 + 1); // error: safe but the compiler can't tell
这样也可以。在您需要getBlogs()
使用数字文字进行调用并且number
不会接受任何-typed参数的情况下,存在相同的问题。与纯联合相比,该解决方案肯定具有更多奇怪的运动部件,因此我不确定我是否真的会在任何生产代码中推荐这样做。但是我确实想展示TypeScript当前距离您想要的行为有多近。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句