Ifa*_*uki 2 javascript typescript
我有一个类似的功能:
function getBlogs(limit?: number) { ... }
Run Code Online (Sandbox Code Playgroud)
只能limit是正整数,不能是0。
我如何告诉打字稿这个数字只能大于0?
有一个公开建议microsoft/TypeScript#15480支持“范围类型”,您可以在其中表示类似的内容 type PositiveWholeNumbers = 1..9999999来表示您的类型。还有一个(已关闭的)建议microsoft/TypeScript#4639支持intanduint类似类型,这也可能在这里工作。遗憾的是,这些都没有实现,所以如果您想在类型系统中实现这一点,您需要做其他事情。
如果有一个相当小的上限(最多数千),您可以手动生成允许值的并集并将其推送到库文件中的某个位置。这可以通过编程方式完成,因此您不必实际键入它,但它与您执行的操作相同:
// 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());
}
Run Code Online (Sandbox Code Playgroud)
这将起作用,因为编译器将看到这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 | ...
Run Code Online (Sandbox Code Playgroud)
当然,超出范围的任何内容都会失败:
getBlogs(1234567); // error (too big)
getBlogs(1e100); // error (too big)
Run Code Online (Sandbox Code Playgroud)
这实际上只在人们使用getBlogs()一些数字文字调用时才有效。数学运算往往会产生number,它太宽而无法验证:
getBlogs(3+1); // error: safe but the compiler can't tell
Run Code Online (Sandbox Code Playgroud)
另外,我还注意到像上面这样的大型联合体的问题足以让我的 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());
}
Run Code Online (Sandbox Code Playgroud)
在这里,该getBlogs()函数接受limit类型 的参数AsPositiveWholeNumber<N>,其中N是由传入的number值推断的约束类型参数。该类型的设计使得 if是正整数,则将是。否则,它将是一个虚拟类型,其目的是向用户提供看似有用的错误消息。limitAsPositiveWholeNumber<N>NAsPositiveWholeNumber<N>NPositiveWholeNumber
重要的工作是在里面完成的AsPositiveWholeNumber<N>。首先我们确保既不N是number也不是0。然后我们通过模板文字类型将其转换为字符串`${N}`,然后确保该字符串版本N不包含"."或"-"字符。这应该主要将正整数与其他数字区分开来,至少在我们得到整数的大值之前,其字符串表示形式以带小数点的指数表示法呈现(例如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
Run Code Online (Sandbox Code Playgroud)
所以这也有效。它也有同样的问题,您需要getBlogs()使用数字文字进行调用,并且任何number类型的参数都不会被接受。这个解决方案肯定比纯联合有更多奇怪的移动部件,所以我不确定我是否真的会在任何生产代码中推荐这个。但我确实想展示 TypeScript 目前可以多么接近您想要的行为。
| 归档时间: |
|
| 查看次数: |
2713 次 |
| 最近记录: |