typescript - 检查打字稿中也可以为空的值是否大于4
问题描述
如何检查在打字稿中初始化为 null 或数字的值是否大于 4?见例子。
years: number | null;
这将给出一个打字稿错误“对象可能是‘空’。”
(years > 4)
解决方案
我假设您在问如何表达名为always的函数参数(或返回值或类属性值)满足的静态要求。x
( x is number && x > 4 ) | null
...也称为Predicate Type、Refinement Type或Dependent Type。
不幸的是,TypeScript(据我所知)还不支持真正的细化类型或谓词类型(尽管它的流分析功能几乎已经存在),但您几乎可以通过 type-def 和 type-guard 来实现:
type NumberGT4OrNull = null | ( number & { _isGT4: never } );
function isNumberGT4OrNull( x: unknown ): x is NumberGT4OrNull {
if( typeof x === 'number' ) {
return x > 4;
}
return false;
}
- 例如,类型声明
type NumberGT4OrNull = null | number;
过于宽松,因为它与 value 匹配1
。 - 将其作为一个成员类型为 as的sum 类型
never
意味着 TypeScript 或 JavaScript 中可能没有任何文字值(或任何其他值)可以匹配NumberGT4OrNull
- 至少在不使用自定义 type-guard 的情况下不会匹配isNumberGT4OrNull
,这可以防止意外使用任何未通过isNumberGT4OrNull
in检查的值类型为 的参数、返回值或属性NumberGT4OrNull
。- ...除了
null
,因为在这种情况下,null
关键字在 sum-type 之外never
。- 但是,如果您想要求
null
检查偶数值,请使用type NumberGT4OrNull = ( null | number ) & { _isGT4: never };
.
- 但是,如果您想要求
- 缺点是你不能不使用,
isNumberGT4OrNull
但这在宏伟的计划中并不是什么大问题。
- ...除了
像这样使用:
function acceptsValue( value: NumberGT4OrNull ): void {
}
//
const userInput = prompt("Enter number");
acceptsValue( userInput ); // Error: userInput is a string
const userInputNumber = parseInt( userInput, 10 );
acceptsValue( userInputNumber ); // Error: userInputNumber is not NumberGT4OrNull
if( isNumberGT4OrNull( userInputNumber ) ) {
acceptsValue( userInputNumber ); // OK! TSC knows `userInputNumber` is `NumberGT4OrNull`.
}
如上所述,使用never
意味着文字值将不匹配,因此以下内容将不起作用并且会给您错误:
acceptsValue( 3 ); // Error
acceptsValue( 4 ); // Error
acceptsValue( 5 ); // Error
acceptsValue( null ); // But this is OK
但是,如果您愿意,可以为方便添加一组(非详尽的)常量值:
type NumberGT4OrNull = null | ( number & { _isGT4: never } ) | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16;
// So now, this does work:
acceptsValue( 3 ); // Error
acceptsValue( 4 ); // Error
acceptsValue( 5 ); // OK!
acceptsValue( null ); // Also OK
const n = 17;
acceptsValue( n ); // Error
if( isNumberGT4OrNull( n ) ) {
acceptsValue( n ); // OK!
}
推荐阅读
- merge - 理解 rxjs6 中的合并(特别是 redux-observable)
- php - php fpm pools error_log 正在写入全局错误日志文件
- linux - 使用期望解释器通过电子邮件通知失败的脚本
- visual-studio - applicationhost.config 中列出的 URL 不在 iis express 中启动
- swift - 如何从firebase下载多个图像?
- python - Elasticsearch:缺少 Content-Type 标头
- kubernetes - 无法通过 SSL 终止使用 cert-manager 和 nginx 入口控制器
- cmd - 如何在 HTA 中一一运行 CMD 命令
- ios - 如何将文件发送到“文件”应用中的“最近删除”文件夹?
- r - 在 R 中取消列出字符串并粘贴/连接