有时不应用 TypeScript 类型限制

标签 typescript

我正在使用 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`
};

当我只是将 AuthenticatedUserLoadingUser 一起使用,或者将 GuestUserLoadingUser 一起使用时,此问题确实存在不会发生。 TypeScript 然后正确地错误并告诉我 loggedInLoadingUser 类型上不存在,就像我想要的那样。

为什么使用类型 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/

相关文章:

TypeScript:具有相同泛型类型的多个参数的函数的混合行为

javascript - 在 fetch 中添加 catch 时出错

android - 从 TypeScript 调用 Android 方法

angular - 类型 'number'的参数不能分配给 'string'类型的参数。将旧项目导入新项目时

javascript - 将 TypeScript 与 Jest 一起使用不会捕获语法错误

typescript - 有人可以向我解释一下 'as never' 在这段代码中做了什么吗?

typescript - bool 值 ('false' ) 返回真

javascript - 如何使用 Typescript + react-leaflet 创建 GeoJSON Feature 元素

javascript - 类型 ref 不可分配给类型 IntrinsicAttributes

reactjs - React Typescript 面临 enzyme 的问题