我正在使用 TypeScript 设计一个身份验证后端。我有以下类型来描述用户或访客:
export type LoadingUser = {
loading: true;
};
export type AuthenticatedUser = {
loading: false;
error: string | null;
loggedIn: true;
name: string;
};
export type GuestUser = {
loading: false;
error: string | null;
loggedIn: false;
};
LoadingUser
用于指示何时仍在获取用户,前端可以在此处显示一个旋转器。请注意,它要么只有loading: true
,没有其他属性,或者loading: false
有其他属性,然后要么loading: false ;登录:假;错误:字符串| null
没有其他属性,或者 loading: false;登录:真实;错误:字符串| null
与其他属性。
然后,我使用这些类型来定义我的 User
类型:
export type User =
| LoadingUser
| AuthenticatedUser
| GuestUser;
我想用它来类型检查我的所有 API 响应,但我遇到了以下问题
const user: User = {
loading: true,
loggedIn: true, // Problem: this property is allowed on this object even though `loading: true`
};
当我只是将 AuthenticatedUser
和 LoadingUser
一起使用,或者将 GuestUser
与 LoadingUser
一起使用时,此问题确实存在不会发生。 TypeScript 然后正确地错误并告诉我 loggedIn
在 LoadingUser
类型上不存在,就像我想要的那样。
为什么使用类型 User
会使 TypeScript 不报告此错误?
提前:非常感谢您帮助我,我已经为此苦苦挣扎好几天了!
最佳答案
export type LoadingUser = {
loading: true;
loggedIn?: never;
};
问题在于,根据类型理论,将 { loading: true,loggingIn: true }
分配给 LoadingUser
是正确的(实际上不应该是错误) -对象符合 LoadingUser
类型约束。 Typescript 的限制 对象字面量只能指定已知属性 是一个额外的帮助器,因为在实践中,在对象字面量中指定未知属性通常是一个错误(或糟糕的类型设计),尽管理论上是可以的,但这个帮助器绝对可以没有捕获所有可能的情况。
但是,通过声明 loggedIn?: never
您明确不允许 LoadingUser
拥有此属性,那么您的“坏”对象将不符合此接口(interface)并报告错误。
关于有时不应用 TypeScript 类型限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62269282/