簡體   English   中英

Typescript 屬性僅在另一個屬性存在時才允許

[英]Typescript property only allowed if another property exists

假設我有一個 function,如果存在另一個屬性,我只想在其中允許一個屬性。

我試着這樣做,但它返回錯誤Property 'c' does not exist on type 'A'.

type A = {
  a?: string;
} & ({ b: string; c?: string } | { b?: string });

const sad = (props: A) => {
  const { a, b } = props;

  const { c } = props;  // Property 'c' does not exist on type 'A'.

  return { a, b };
};

有什么解決辦法嗎?

我知道的唯一方法是用戶定義的類型保護,我喜歡將它與聯合類型結合起來

interface CommonProps {
    a?: string
    b?: string
}

interface SimpleProps extends CommonProps {
    kind: "simple"
}

interface ComplexProps extends CommonProps {
    kind: "complex"
    c?: string
}


type Props = SimpleProps | ComplexProps

function isComplex(arg: Props): arg is ComplexProps {
    return arg && arg.kind === 'complex'
}

const sad = (props: Props): any => {
    if (isComplex(props)) {
        const {a, b, c} = props
        // do something
        // return something
    }
    const { a, b } = props
    // do something
    // return something
}

簡而言之,我為每個可能的屬性組合創建了一個接口。 然后我將它們合並到Props類型下,並在我的 function 中使用user defined guards來訪問屬性。

聯合類型只保留兩種類型共有的屬性。 在下面的聯合中,結果類型只有一個屬性: b: string | undefined b: string | undefined

{ b: string; c?: string } | { b?: string }

下面的代碼將實現你最初的預期,我認為:

type A = {
  a?: string;
} & ({ b: string; c?: string; } | { b?: undefined; });

const sad = (props: A) => {
  const { a, b } = props;

  if (b) {
    const { c } = props;

    return { a, b, c };
  }

  return { a, b };
};

在 condition 之外,你不能使用c ,但在 condition 內部, props的類型已經縮小。 現在b不能是undefined ,編譯器知道c

我只能使用類型和 generics 生成它:

type SelectedOptional<Base, T extends (string | number | symbol) & keyof Base> = {
  [Key in keyof Base]: Base[Key];
} & {
  [Key in T]: Base[Key];
};

type SelectedNever<Base, T extends string | number | symbol> = {
  [Key in keyof Base]: Base[Key];
} & {
  [Key in T]?: never;
};

export type Dependant<BaseAttributes, DependantAttributes extends keyof BaseAttributes> =
  | SelectedOptional<BaseAttributes, DependantAttributes>
  | SelectedNever<BaseAttributes, DependantAttributes>;

您指定包含所有屬性(以及依賴屬性)的基本屬性,然后指定哪 2 個(或更多)相互依賴,如下所示:

這將起作用:

const exampleObject: Dependant<SomeBaseAttributes, 'dependant1' | 'dependant2'> = {
  attr1: 1,
  attr2: 2, 
 };

這將失敗,因為您還需要指定屬性“dependant2”:

const exampleObject: Dependant<SomeBaseAttributes, 'dependant1' | 'dependant2'> = {
  attr1: 1,
  attr2: 2,
  dependant1: 3
};

暫無
暫無

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

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