代码之家  ›  专栏  ›  技术社区  ›  Issac Howard

理解typescript中的“is”关键字

  •  1
  • Issac Howard  · 技术社区  · 1 年前

    我想了解我在Typescript/Angular中看到的一个特定模式,如下所示:

    this.subscription = this.router.events
        .pipe(
            filter((routingEvent: any): routingEvent is NavigationEnd => routingEvent instanceof NavigationEnd),
    

    据我所知,“is”关键字缩小了 类型 。这意味着 Angular's RouterEvent 类变成了它的子类 NavigationEnd 。然后我们检查 routingEvent 是个例子 导航结束 。我有两个问题:

    • 如果我们使用“map()”并说 routingEvent is NavigationEnd ?
    • 在里面 filter() ,我们说过 routingEvent为NavigationEnd 。这会改变我们订阅时的输出吗?如果是这样,我们为什么不能 return true 因为我们只是宣称 routingEvent为NavigationEnd ?

    如果这些问题有缺陷,请原谅我,因为我是打字的新手,但如果有人能帮助我,那就太好了。

    3 回复  |  直到 1 年前
        1
  •  2
  •   Matthieu Riegler    1 年前

    这个 is typescript中的关键字用于描述 predicate .

    谓词用于用户定义的类型保护。

    当你有

    (routingEvent: any): routingEvent is NavigationEnd => routingEvent instanceof NavigationEnd),
    

    函数通过断言引入类型安全性 routingEvent 属于类型 NavigationEnd

        2
  •  1
  •   Nicholas Tower    1 年前

    根据我的理解,“is”关键字缩小了一种类型。这意味着Angular的RouterEvent类变成了它的子类NavigationEnd。

    是的,但前提是函数返回true。 routingEvent is NavigationEnd 意思是“我将返回一个布尔值,如果我返回true,typescript应该假设事件是 NavigationEnd ".

    如果我们使用“map()”并说routingEvent是NavigationEnd,这不是更有效吗

    那样做会有完全不同的结果。过滤方法的目的是 去除 事件流中的事件。映射将保留所有内容,包括不是NavigationEnd事件的内容。

    在filter()中,我们说过routingEvent是NavigationEnd。这会改变我们订阅时的输出吗?

    对事实上,我们正在识别NavigationEnd事件,然后返回true或false,这将改变运行时的输出。事实上,我们使用了 routingEvent为NavigationEnd 而不是 boolean 将允许typescript在编译时反映这种类型缩小。

    如果是这样,为什么我们不能直接返回true,因为我们刚刚声明routingEvent是NavigationEnd?

    这是法律法规,但它违背了目的,会导致漏洞。filter函数的目标是只允许NavigationEnd事件通过。如果你只是返回true,你允许 每件事 以滑过过滤器。然后返回类型是一个谎言。你告诉typescript“我检查了这个,它是NavigationEnd.”,但你没有。typescript在编译时会信任你,但在运行时会出错。

        3
  •  1
  •   Naren Murali    1 年前

    Typescript是为 static type checking 在您的问题中,这意味着我们不操纵值,我们只是使用typescript来定义类型,以捕获由于分配了不正确的类型而导致的最大类型错误。

    现在让我们开始讨论您的问题。

    如果我们使用“map()”并说routingEvent是NavigationEnd,这不是更有效吗?

    答:没有,因为 map 将返回所有值,目的是 filter 这里是使用javascript instanceof 运算符过滤掉所有 NavigationEnd 单独的事件,所以所有其他事件(例如。 NavigationStart ,等等没有订阅)这就是我们使用filter的原因!其次 router.events 具有一种类型 Event_2 以下是它的类型定义

    declare type Event_2 = NavigationStart | NavigationEnd | 
    NavigationCancel | NavigationError | RoutesRecognized | 
    GuardsCheckStart | GuardsCheckEnd | RouteConfigLoadStart | 
    RouteConfigLoadEnd | ChildActivationStart | ChildActivationEnd | 
    ActivationStart | ActivationEnd | Scroll | ResolveStart | 
    ResolveEnd | NavigationSkipped;
    

    正如你所看到的,它是所有路由器事件的联合,所以当我们订阅它时,它显然会混淆typescript!

    所以我们使用 is 关键字,将类型和资产缩小到返回类型的typescript 导航结束

    在filter()中,我们说过routingEvent是NavigationEnd。这会改变我们订阅时的输出吗?如果是这样,为什么我们不能直接返回true,因为我们刚刚声明routingEvent是NavigationEnd?

    答:不,typescript只是一个开发层实体,这意味着它有助于开发,不会干扰返回值,它的目的是帮助开发人员捕捉错误并编写干净的代码,注意typescript确实会将代码转换为javascript,当我们将它们转换为javascript时,我们有一些运算符会转换为不同的结构

    Typescript playgroud example

    因此,为了回答您的问题,typescript不会转换任何内容,我们使用filter的原因是过滤掉事件,而且只有当我们这样做时,我们才会返回布尔条件 routingEvent instanceof NavigationEnd

    推荐文章