簡體   English   中英

TypeScript:如何正確縮小交叉類型的聯合

[英]TypeScript: How to properly narrow a Union of Intersection Types

我目前正在構建一個接受一些路由的組件,並制作一個帶有嵌套路由器視圖的步進器。

我在滿足 TypeScript 方面遇到了一些麻煩。

我正在使用vue-routerRouteLocationRaw類型。

RouteLocationRawstring和兩個交叉點類型的並集,定義為

export declare type RouteLocationRaw = string | (RouteQueryAndHash & LocationAsPath & RouteLocationOptions) | (RouteQueryAndHash & LocationAsRelativeRaw & RouteLocationOptions);

export declare interface RouteQueryAndHash {
    query?: LocationQueryRaw;
    hash?: string;
}

export declare interface LocationAsPath {
    path: string;
}

export declare interface RouteLocationOptions {
    replace?: boolean;
    force?: boolean;
    state?: HistoryState;
}

export declare interface LocationAsRelativeRaw {
    name?: RouteRecordName;
    params?: RouteParamsRaw;
}

我想做的是將當前路由的名稱與傳遞給組件的名稱進行比較,如下所示

const activeRoute = computed(() => props.routes.find((propRoute) => propRoute.name === route.name))

這個邏輯按我的意願工作,但 TypeScript 抱怨。 使用上述方法,我得到以下錯誤。

Property 'name' does not exist on type 'RouteLocationRaw'.
  Property 'name' does not exist on type 'string'.

TypeScript 似乎自動假定類型是一個字符串,它是聯合的第一部分。 假設已經是一件奇怪的事情,但是縮小到字符串之外也沒有幫助。

如果我添加一個案例來處理string type的路由 TypeScript 仍然無法識別該name可能是route的屬性。

Property 'name' does not exist on type '(RouteQueryAndHash & LocationAsPath & RouteLocationOptions) | (RouteQueryAndHash & LocationAsRelativeRaw & RouteLocationOptions)'.
  Property 'name' does not exist on type 'RouteQueryAndHash & LocationAsPath & RouteLocationOptions'.

我將把你的代碼簡化為這個,它有同樣的錯誤。

declare const propRoute: RouteLocationRaw // the current route, lets say

if (propRoute.name === 'foo') {
  console.log('foo is active')
}

現在要訪問任何值的屬性,該類型必須聲明該屬性。 當您訪問聯合的屬性時,該聯合的所有成員都必須聲明這一點。 所以 typescript 不是假設值是string ,它告訴你它可能是一個string ,如果是,那么這個屬性訪問沒有任何意義。

因此,要訪問name屬性,您需要將聯合范圍縮小到支持name屬性的類型。 因此,您必須過濾掉string ,並且必須過濾掉缺少該屬性的 object 屬性。

這可能看起來像這樣:

if (
  typeof propRoute !== 'string' && // filter out string.
  'name' in propRoute && // require the `name` property.
  propRoute.name === 'foo' // check the name proeprty.
) {
  console.log('foo is active')
}

看游樂場

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM