首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在类型保护类型上传播会导致类型检查被跳过?

为什么在类型保护类型上传播会导致类型检查被跳过?
EN

Stack Overflow用户
提问于 2021-03-08 23:26:03
回答 1查看 58关注 0票数 7

问题:

当我忘记向T类型的对象添加嵌套字段时,以及在使用对象扩展构造所述对象时,为什么不接收编译时错误?

示例:

代码语言:javascript
复制
interface User {
  userId: number;
  profile: {
    username: string
  }
}

function updateUsername(user: User): User {
  return {
    ...user,
    profile: {
      // Error (as expected)
    }
  }
}

function updateUsernameGeneric<T extends User>(user: T): T {
  return {
    ...user,
    profile: {
      // No error (unexpected... why?)
    }
  }
}

我自己对答案的推测:

我所能想象的是,TypeScript允许子类型移除其超类的属性,这使得对于某些子类型T of Userprofile属性可能不包含任何属性成为可能。(如果是这样的话,我不知道TypeScript允许你这么做.)

TypeScript版本4.1.2

游乐场

EN

回答 1

Stack Overflow用户

发布于 2021-03-09 01:26:58

这与与普通类型相比如何使用泛型类型(请参阅按下)解析传播有关。如果将结果对象写入变量,您将立即注意到不同之处:对于非泛型类型,合并类型推断为:

代码语言:javascript
复制
{
    profile: {};
    userId: number;
}

这导致此类型不可分配给带注释的返回类型User,该类型具有所需的username子属性。这正是编译器错误TS 2322所告诉您的:

属性'username‘在类型'{}’中缺失,但在类型'{ username: string;}‘中是必需的

现在,泛型的情况有点不同:实际上,泛型被推断为User的子类型和{ profile: {}; }类型的交集:

代码语言:javascript
复制
T & {
    userId: string;
    profile: {};
}

编译器可以这样做,因为交集是带注释的返回类型的“扩展”,它包含所有的属性,如交集的定义所示。

这是否是一种良好的行为是值得商榷的,因为您可以这样做,编译器也不会更明智:

代码语言:javascript
复制
function updateUsernameGeneric<T extends User>(user: T): T {
  const newUser = {
    ...user,
    userId: "234",
    profile: {
      // No error (unexpected... why?)
    }
  }

  return newUser;
}

updateUsernameGeneric({ profile: { username: "John" }, userId: 123 }).userId //a-ok, "number"

因为返回类型是泛型类型参数和合并属性的交集,所以可以取消对返回类型的注释并让TypeScript推断它。不兼容的属性类型将被正确推断为never

代码语言:javascript
复制
function updateUsernameGenericFixed<T extends User>(user: T) {
  const newUser = {
    ...user,
    userId: "234",
    profile: {
      // No error (unexpected... why?)
    }
  }

  return newUser;
}

updateUsernameGenericFixed({ profile: { username: "John" }, userId: 123 }).userId //never

游乐场

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66538678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档