如何访问可选属性的“类型”属性?

时间:2019-11-08 09:57:03

标签: typescript

请参见下面的代码段

interface MyObj {
  myOptionalProp: MyOptionalPropObj;  // NOT OPTIONAL
} 

interface MyOptionalPropObj {
  myProp1: SomeType;
  myProp2?: SomeType;
}

type Test1 = MyObj['myOptionalProp']['myProp1'];  // Works
type Test2 = MyObj['myOptionalProp']['myProp2'];  // Works

如果MyObj不是可选的,则访问Test1中要分配给Test2myOptionalProp的嵌套属性会很好。

但是。一旦myOptionalProp是可选的:

interface MyObj {
  myOptionalProp?: MyOptionalPropObj; // OPTIONAL
} 

interface MyOptionalPropObj {
  myProp1: SomeType;
  myProp2?: SomeType;
}

type Test1 = MyObj['myOptionalProp']['myProp1'];  // Doesn't work
type Test2 = MyObj['myOptionalProp']['myProp2'];  // Doesn't work

TypeScript引发此错误:

Property 'myProp1' does not exist on type 'MyOptionalPropObj | undefined'.ts(2339)

访问类型时是否有断言的方法?就像

myObj.myOptionalProp!.myProp1

可是type秒?


在本例中,MyObj类型是在我们的情况下自动生成的,特别是GraphQL代码生成器,并且我们无法控制其结构。我们可以简单地直接使用类型SomeType,但这目前不是一个选择。

自动生成的类型示例为:

export type TestQuery = (
  { __typename?: 'Query' }
  & { profile: Maybe<(
    { __typename?: 'Profile' }
    & Pick<Profile, 'id' | 'name' | 'updatedAt' | 'createdAt'>
    & { owner: Maybe<(
      { __typename?: 'User' }
      & Pick<User, 'id' | 'displayName'>
    )>, users: Maybe<Array<(
      { __typename?: 'User' }
      & Pick<User, 'id' | 'displayName'>
    )>> }
  )> }
);

在此示例中,我们无法访问owner的{​​{1}}属性,因为所有者可能未定义。

profile

1 个答案:

答案 0 :(得分:2)

如果属性是可选的,则其类型将与未定义的联合,并且由于只能访问联合的公共属性,因此原始类型的所有属性都将不可访问。

您需要从联合中删除undefined。预定义的条件类型Exclude将达到目的:

interface MyObj {
    myOptionalProp?: MyOptionalPropObj; // OPTIONAL
}

interface MyOptionalPropObj {
    myProp1: string;
    myProp2?: number;
}

type Test1 = Exclude<MyObj['myOptionalProp'], undefined>['myProp1']; //ok
type Test2 = Exclude<MyObj['myOptionalProp'], undefined>['myProp2'];  // ok

Playground Link