我可以使对象属性类型依赖于另一个属性类型吗?

时间:2019-04-29 15:53:01

标签: typescript conditional-types

我有一个看起来像这样的对象:

interface AuthState {
  isSignedIn: boolean
  token?: string
  user?: User
}

user可以是未定义的,但是只有isSignedIn === false才可以。在应用程序中,不可能有isSignedIn === true并且没有用户对象。我希望能够执行该操作,而不必执行以下操作:

// If I don't check for `user`, TS will throw an error since it doesn't see any
// relation between the 2 properties
const userName = isSignedIn && user && user.name

1 个答案:

答案 0 :(得分:0)

如果我理解您的问题,那应该就是您要寻找的东西。

interface FalseAuthState {
  isSignedIn: false;
}

interface TrueAuthState {
  isSignedIn: true;
  token: string;
  user: User;
}

type AuthState = FalseAuthState | TrueAuthState;

现在,如果您要拥有

之类的对象,
// This does not throw an error because Typescript knows it's correct
const noAuth: AuthState = {
   isAuth: false
} 

// This will throw an error because Typescript demands a User and Token.
const yesAuth: AuthState = {
   isAuth: true
} 

// This will not throw an error.
const realAuth: AuthState = {
  isAuth: true,
  token: "ABCD123",
  user: new User()
} 

function printUser(auth: AuthState) {
  if (auth.isAuth) {
     console.log(auth.user); // Typescript knows there's supposed to be a user so there is no error
  }
}

function badPrintUser(auth: AuthState) {
   if (auth.isAuth === false) {
      console.log(auth.user); // Typescript will throw an error because there's no supposed to be a user here.
   }
}

在您的示例中,检查方式如下:

const userName = auth.isSignedIn && auth.user.name

const userName = auth.isSignedIn ? auth.user.name : undefined;

不幸的是,您将无法从对象本身中删除属性,并利用它来发挥自己的优势。如果要这样做

const { isSignedIn, user } = (auth as TrueAuthState);
const userName = isSignedIn && user && user.name; // You still have to do this unless you really sure that the auth is a TrueAuthState