为什么新的 Pick 类型允许 React 的 setState() 中 K 的子集?

2024-02-23

我以为我明白了新的目的TS 2.1 Pick type https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html#partial-readonly-record-and-pick,但后来我看到它是如何在 React 类型定义中使用的 https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/react/index.d.ts#L171我不明白:

declare class Component<S> {
    setState<K extends keyof S>(state: Pick<S, K>, callback?: () => any): void;
    state: Readonly<S>;
}

这允许你这样做:

interface PersonProps {
  name: string;
  age: number;
}

class Person extends Component<{}, PersonProps> {
  test() {
    this.setState({ age: 123 });
  }
}

我的困惑是keyof S is { name, age }但我打电话setState()仅与age——为什么它不抱怨失踪name?

我的第一个想法是因为Pick是一种索引类型,它根本不需要所有键都存在。说得通。但如果我尝试直接分配类型:

const ageState: Pick<PersonProps, keyof PersonProps> = { age: 123 };

It does抱怨失踪name key:

Type '{ age: number; }' is not assignable to type 'Pick<PersonProps, "name" | "age">'.
  Property 'name' is missing in type '{ age: number; }'.

我不明白这一点。它seems我所做的只是填写S与类型S已经分配给,并且它从允许sub-set要求的关键all键。这是一个很大的区别。这是在操场上 http://www.typescriptlang.org/play/#src=declare%20class%20Component%3CP%2C%20S%3E%20%7B%0A%20%20%20%20setState%3CK%20extends%20keyof%20S%3E(state%3A%20Pick%3CS%2C%20K%3E%2C%20callback%3F%3A%20()%20%3D%3E%20any)%3A%20void%3B%0A%20%20%20%20state%3A%20Readonly%3CS%3E%3B%0A%7D%0A%0Ainterface%20PersonProps%20%7B%0A%20%20name%3A%20string%3B%0A%20%20age%3A%20number%3B%0A%7D%0A%0Aclass%20Person%20extends%20Component%3C%7B%7D%2C%20PersonProps%3E%20%7B%0A%20%20test()%20%7B%0A%20%20%20%20const%20person%3A%20Pick%3CPersonProps%2C%20keyof%20PersonProps%3E%20%3D%20%7B%20age%3A%20123%20%7D%3B%0A%20%20%20%20this.setState(%7B%20age%3A%20123%20%7D)%3B%0A%20%20%7D%0A%7D。谁能解释这种行为?


简短回答:如果你真的想要一个显式类型,你可以使用Pick<PersonProps, "age">,但使用隐式类型更容易。

长答案:

关键点是K是一个泛型类型变量extends keyof T.

方式keyof PersonProps等于字符串并集"name" | "age"。方式"age"可以说是扩展类型"name" | "age".

回想一下定义Pick is:

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
}

这意味着对于每个K,该类型描述的对象必须有一个属性P与房产类型相同K in T。您的示例游乐场代码是:

const person: Pick<PersonProps, keyof PersonProps> = { age: 123 };

解开泛型类型变量,我们得到:

  • Pick<T, K extends keyof T>,
  • Pick<PersonProps, "name" | "age">,
  • [P in "name" | "age"]: PersonProps[P],最后
  • {name: string, age: number}.

这当然是不兼容的{ age: 123 }。如果你改为说:

const person: Pick<PersonProps, "age"> = { age: 123 };

然后,遵循相同的逻辑,类型person将正确地等同于{age: number}.

当然,无论如何,TypeScript 都会为你计算所有这些类型——这就是你得到错误的原因。由于 TypeScript 已经知道类型{age: number} and Pick<PersonProps, "age">是兼容的,你不妨保持类型隐式:

const person = { age: 123 };
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么新的 Pick 类型允许 React 的 setState() 中 K 的子集? 的相关文章

随机推荐

  • 查找 2D 数组/矩阵中 k 个最高值的索引

    我有一个包含值的 2D 矩阵 我想找到前 5 个值的索引 例如对于 matrix 0 17542851 0 13199346 0 01579704 0 01429822 0 01302919 0 13279703 0 12444886 0
  • 自动完成jquery和SQL,ASP.NET

    我正在尝试使用 jquery 创建一个自动完成文本框 它将绑定到 SQL 数据库 我还想在页面上放置一个下拉列表 以便根据初始选择自动完成文本框将从不同的表中检索数据 这是一个 ASP NET 2 0 页面 背后的代码是 VB NET 我有
  • Swift:可选下标的可选链接

    我有一个let map String String and a let key String 最简洁的访问方式是什么map key 并取回String 如果我有一个key and None如果我没有 let value key flatMa
  • 如何在 ASP.NET MVC 控制器中使用 Automapper 配置

    我正在使用 AutoMapper 将模型转换为视图模型 我已经完成所有设置 测试和工作 作为参考 我的配置方法如下所示 public static MapperConfiguration Configure MapperConfigurat
  • Rails:更改生产数据库的最佳方法

    我需要对正在使用的生产数据库进行更改 只需添加几列即可 我已经通过迁移对开发数据库进行了更改 在保留现有数据且不会过多干扰操作的情况下更新生产数据库的最佳方法是什么 它是 MYSQL 我还需要向列添加数据以及现有记录 一列可以有默认值 它是
  • 如何在 docker 容器内使用 nginx 提供静态文件?

    因为我运行的是 Mac OSX 所以我使用 boot2docker 我不知道如何使用在 docker 容器内运行的 nginx 也包含静态资产 如我的 html 和 js 提供静态文件 我有四个 docker 容器正在与此一起旋转docke
  • 存储库模式实现

    似乎我找到的存储库模式的每个示例 其实现都在某种程度上有所不同 下面是我主要找到的两个例子 interface IProductRepository IQueryable
  • 由于 Xcode 11 中不再包含应用程序加载器,如何上传 IPA

    我有点害怕问这个问题 因为这个问题对我来说似乎很大 但我没有看到有人对此感到恐慌 我有点害怕听起来很疯狂 但我会坚持下去 正如我们可以在苹果的帖子中看到的提交更新 https developer apple com app store co
  • 如何在 Angular 2 中使用 Less?

    我想知道如何在我的 Angular 2 项目中添加更少的编译 因为每个组件都有自己的 css 文件 现在将是 less文件 我不确定如何使文件编译为 css 我也用谷歌搜索了这个问题 但没有找到任何解决我的问题的方法 EDIT为了让我的问题
  • 比较字符串 Javascript 返回可能的百分比

    我正在寻找一个 JavaScript 函数 它可以比较两个字符串并返回它们相似的可能性 我看过 soundex 但对于多单词字符串或非名称来说并不是很好 我正在寻找一个类似的函数 function compare strA strB com
  • Foursquare Venue Api:生成“8/10 人喜欢这个地方”的信息

    当查看 FourSquare 页面时 例如 巴黎旺多姆广场 https foursquare com v place vend C3 B4me 4adcda09f964a5200e3421e3 显示文本 9 4 10 人们喜欢这个地方 我想
  • 由于可能的配置错误,请求超出了 10 个内部重定向的限制。?

    我有一个简单的重写 RewriteRule addnew 0 不过我得到了 Request exceeded the limit of 10 internal redirects due to probable configuration
  • c# System.guid 不包含 Parse 的定义

    AT Anchor System Guid Parse DataBinder Eval e Item DataItem Anchor ToString 这会抛出 System Guid does not contain a definiti
  • “clr-namespace”URI 引用未包含在程序集中的命名空间

    我试图在我的 XAML 中包含一些转换值的类 但是 当我编译时 我收到以下错误 未定义的 CLR 命名空间 clr namespace URI 引用未包含在程序集中的命名空间 View Summary Converters View Vie
  • 角度 4 中的动画路线

    我正在尝试以角度 4 为路线过渡设置动画 动画在页面首次加载和页面刷新时起作用 所以我知道动画有效 但在我切换路线时则不然 我缺少什么 这是代码 组件元数据 animations fadeInAnimation 模板 div class r
  • iPhone 开发:初学者资源

    正如标题所说 您有任何可用资源来开始为 iPhone 进行开发吗 书籍 在线资源 工具 开发环境 先决条件以及与iPhone编程相关的一切都会很好 Thanks 假设您是初学者 对于书籍而言 此列表是一个很好的起点 http cocoade
  • 如何选择一定长度的数据项?

    如何选择列中的行以使行大小 例如 身份证号 名字 仅选择名字超过 10 个字符的人 他们的名字太长 如果您必须使用特定的 RDBMS 那么解决方案很简单 Use the LENGTH function 根据您的数据库 长度函数可以是 LEN
  • 在非 boost 线程中使用 boost::thread_specific_ptr

    我正在阅读文档部分boost thread specific ptr http www boost org doc libs 1 55 0 doc html thread thread local storage html 并尝试解析这一段
  • 无法在 Windows 上打印彩色文本

    我是 Python 新手 试图在控制台中打印彩色文本 我的操作系统是windows 10 代码如下 class bcolors Colors for console HEADER 033 95m YGREEN 033 92m WARNING
  • 为什么新的 Pick 类型允许 React 的 setState() 中 K 的子集?

    我以为我明白了新的目的TS 2 1 Pick type https www typescriptlang org docs handbook release notes typescript 2 1 html partial readonl