Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TypeScript中的类型安全谓词函数_Typescript_Predicate - Fatal编程技术网

TypeScript中的类型安全谓词函数

TypeScript中的类型安全谓词函数,typescript,predicate,Typescript,Predicate,我的目标是在TypeScript中编写谓词函数(isNull和isUndefined),这些函数满足以下条件: 可以独立使用:array.filter(isNull) 可以逻辑组合:array.filter(和(非(isNull)、非(isUndefined)) 使用类型保护,以便TypeScript知道例如array.filter(isNull)的返回类型将是null[] 组合谓词可以提取到新的谓词函数中,而无需中断类型推断:const isNotNull=not(isNull) 前两个条件很

我的目标是在TypeScript中编写谓词函数(
isNull
isUndefined
),这些函数满足以下条件:

  • 可以独立使用:
    array.filter(isNull)
  • 可以逻辑组合:
    array.filter(和(非(isNull)、非(isUndefined))
  • 使用类型保护,以便TypeScript知道例如
    array.filter(isNull)
    的返回类型将是
    null[]
  • 组合谓词可以提取到新的谓词函数中,而无需中断类型推断:
    const isNotNull=not(isNull)
  • 前两个条件很容易满足:

    type谓词=(i:any)=>boolean;
    常量和=(p1:谓词,p2:谓词)=>
    (i:任何)=>p1(i)和p2(i);
    常量or=(p1:谓词,p2:谓词)=>
    (i:任何)=>p1(i)| | p2(i);
    常量not=(p:谓词)=>
    (i:任何)=>!p(i);
    常量isNull=(i:any)=>
    i==null;
    常量isUndefined=(i:any)=>
    i==未定义;
    const items=[“foo”,null,123,未定义,true];
    const filtered=items.filter(and(not(isNull)、not(isUndefined));
    console.log(过滤);
    
    但由于此处未使用类型保护,TypeScript假定变量
    筛选后的
    具有相同的类型,即
    (字符串、数字、布尔值、null、未定义)[
    ,而实际上现在应该是
    (字符串、数字、布尔值)[

    所以我添加了一些打字脚本魔术:

    type Diff=T扩展U?从不:T;
    类型谓词=(i:i)=>i是O;
    常量和=(p1:谓词,p2:谓词)=>
    (i:i):i是(O1和O2)=>p1(i)和p2(i);
    常量or=(p1:谓词,p2:谓词)=>
    (i:i):i是(O1 | O2)=>p1(i)| p2(i);
    常量not=(p:谓词)=>
    (i:i):我是(Diff)=>!p(i);
    常量isNull=(i:i | null):i为null=>
    i==null;
    常量未定义=(i:i |未定义):i未定义=>
    i==未定义;
    
    现在它似乎可以工作了,
    过滤后的
    被正确地简化为类型
    (字符串、数字、布尔)[

    但是由于
    not(isNull)
    可能经常被使用,我想将其提取到一个新的谓词函数中:

    const isNotNull=not(isNull);
    
    虽然这在运行时非常有效,但不幸的是它没有编译(启用严格模式的TypeScript 3.3.3):

    类型为“(i:i | null)=>i为null”的
    参数不能分配给类型为“Predicate”的参数。
    类型谓词“i为null”不能赋值给“i为{}”。
    类型“null”不可分配给类型“{}”。ts(2345)
    
    因此,我猜想当使用谓词作为数组
    过滤器
    方法的参数时,TypeScript可以从数组中推断
    I
    的类型,但是当将谓词提取到单独的函数中时,这将不再起作用,TypeScript返回到基本对象类型
    {}
    ,这会破坏一切


    有办法解决这个问题吗?在定义
    isNotNull
    函数时,有什么技巧可以说服TypeScript坚持使用泛型类型
    I
    ,而不是将其解析为
    {}
    ?或者这是TypeScript的一个限制,目前无法完成?

    这就是您要找的吗


    const isNotNull=not(isNull)

    从上下文传递类型信息。这段代码编译得很好

    // c: (string | number)[]
    let c = [1, 2, 'b', 'a', null].filter(not<number | string | null, null>(isNull)); 
    
    /c:(字符串|数字)[]
    设c=[1,2,'b','a',null].filter(not(isNull));
    
    No。这修复了编译器错误,但破坏了类型安全。如果使用此函数过滤数组,则返回值为
    any[]
    这是一个很酷的主意!您使用什么TS版本?您的代码现在在TS游乐场中运行良好<代码>设a2=[1,2,'sdfsf',null]。筛选器(isNotNull);//让a2:(string | number)[
    我在严格模式下使用最新的Typescript 3.3.3。至少启用TS Playway中的
    strictNullChecks
    选项以重现问题。它不会编译,在您的示例中,将鼠标悬停在
    a2
    上会显示错误的类型
    never[]
    。TS的一个缺点是不能将用户定义的类型保护与标准返回类型混合使用。我不确定您想做什么是可能的,您需要从头定义
    isNotNull
    ,而不是编写它@kayahr,我认为,这是编译器错误,因为在非严格模式下,编译器会按预期检测类型
    // c: (string | number)[]
    let c = [1, 2, 'b', 'a', null].filter(not<number | string | null, null>(isNull));