首页 > 解决方案 > 检查打字稿中也可以为空的值是否大于4

问题描述

如何检查在打字稿中初始化为 null 或数字的值是否大于 4?见例子。

years: number | null;

这将给出一个打字稿错误“对象可能是‘空’。”

(years > 4)

标签: typescript

解决方案


我假设您在问如何表达名为always的函数参数(或返回值或类属性值)满足的静态要求x( x is number && x > 4 ) | null

...也称为Predicate TypeRefinement TypeDependent 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,这可以防止意外使用任何通过isNumberGT4OrNullin检查的值类型为 的参数、返回值或属性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!
}

游乐场链接


推荐阅读