簡體   English   中英

Typescript 屬性在擴展類型上不存在

[英]Typescript property does not exist on extended type

我有一個 react 組件,它可以使用to (react-router-dom prop) 或href屬性,具體取決於我要重定向用戶的位置; 無論是在應用程序內還是外部 url。 Typescript 抱怨我的類型

類型“LinkType”上不存在屬性“to”。

類型“LinkType”上不存在屬性“href”。

這就是我定義我的類型的方式

import React from 'react';
import { Link } from 'react-router-dom';

interface LinkBase {
  label: string;
  icon?: JSX.Element;
}

interface RouterLink extends LinkBase {
  to: string;
}

interface HrefLink extends LinkBase {
  href: string;
}

type LinkType = RouterLink | HrefLink;

export function NavLink(props: LinkType) {
  const { to, label, icon, href } = props;  // TS complains about those to and href

  return(
    {to ? (
      <Link to={to}>{label}</Link>
    ) : (
      <a href={href}>{label}</a>
    )}
  );
}

因為LinkType是一個聯合體, HrefLinkRouterLink都可以分配給LinkType HrefLink上沒有“to”,RouterLink 上也沒有“href”。 因此 typescript 不能保證這些屬性中的任何一個都存在於並集上。 您可以使用類型保護來做您想做的事情,同時滿足 TypeScript。

import React from 'react';
import { Link } from 'react-router-dom';

interface LinkBase {
  label: string;
  icon?: JSX.Element;
}

interface RouterLink extends LinkBase {
  to: string;
}

interface HrefLink extends LinkBase {
  href: string;
}

type LinkType = RouterLink | HrefLink;

function isRouterLink(v: unknown): v is RouterLink {
  return v && Object.prototype.hasOwnProperty.call(v, 'to');
}

function isHrefLink(v: unknown): v is HrefLink {
  return v && Object.prototype.hasOwnProperty.call(v, 'href');
}

export function NavLink(props: LinkType) {
  const { label, icon } = props; 

  if (isRouterLink(props)) {
    const { to } = props; // typechecks now
    return (<> ... </>)
  }

  if (isHrefLink(props)) {
    const { href } = props;

    return (<> ... </>);
  }

  return (<> ... </>);
}

另一種選擇是使用“標記”聯合來解決對類型保護 function 的需求。 這些 go 有一些不同的名稱,具體取決於您與誰交談。 您可以找到這些的其他名稱是“歧視性工會”和“不相交工會”來命名一對。

interface LinkBase {
  label: string;
  icon?: JSX.Element;
}

interface RouterLink extends LinkBase {
  type: 'router';
  to: string;
}

interface HrefLink extends LinkBase {
  type: 'href';
  href: string;
}

type LinkType = RouterLink | HrefLink;

export function NavLink(props: LinkType) {
  const { label, icon } = props; 

  if (props.type === 'router') {
    const { to } = props; // typechecks now
    return (<> ... </>);
  }

  if (props.type === 'href') {
    const { href } = props;

    return (<> ... </>);
  }

 return (<> ... </>); 
}

因此,如果您檢查LinkType['type']您將看到'router' | 'href' 'router' | 'href'和 TypeScript 可以自動縮小類型,如果您對 LinkType 的此類型屬性執行 if 語句。

你可以這樣做:

type LinkType = RouterLink & HrefLink;

這樣你就不必用代碼縮小聯合

編輯 1。
亞歷克斯·D 提出了這種方法可能產生的副作用。 基本上,如果不滿足所有屬性( hreflabelto ),您將無法定義 LinkType object ,這可以通過使用 Partials 或簡單地將hrefto聲明為可選來解決,例如

interface HrefLink extends LinkBase {
  href?: string;
}

暫無
暫無

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

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