我一直在用TypeScript重构我们的一些React应用程序,遇到了一个障碍,我不得不解决,在我看来,一个非常丑陋的双类型参数.这是TypeScript中的一个bug,还是我遗漏了一些类型歧义,导致回调参数默认为"any"类型?

我通过将原始类型隐藏到另一个类型参数中来解决这个问题,这似乎修复了回调方法从"extends string"条件推断错误类型.

原代码:

type Optional<TItem> = TItem extends string
  ? { get?: (item: TItem) => string }
  : { get: (item: TItem) => string };

type TItem = { hello: string } | string;

const obj: Optional<TItem> = {
  get: item => typeof item === 'string' ? item : item.hello
};

原始代码从npx tsc开始的输出(打字5.4.2):

error TS7006: Parameter 'item' implicitly has an 'any' type.

18   get: item => typeof item === 'string' ? item : item.hello

解决方法:

type TItem = { hello: string } | string;

type Optional<TItem, TItemType> = TItemType extends string
  ? { get?: (item: TItem) => string }
  : { get: (item: TItem) => string };

const obj: Optional<TItem, TItem> = {
  get: item => typeof item === 'string' ? item : item.hello
};

推荐答案

你原来的Optional<T>distributive conditional type,这意味着如果Tunion,那么Optional<T>也是union.但这变成了对象的联合,这意味着get是方法的联合,这意味着item方法参数是...嗯,还不清楚.目前,不是discriminated unions的一部分的方法的联合没有contextual type作为其方法参数.在microsoft/TypeScript#48460有一个问题被提交,要求更好的上下文打字,但它被关闭了,因为它像预期的那样工作.A comment询问上下文类型是否应该是联合、intersection或其他类型.也许你对此有意见,但TS团队认为这一点并不清楚,也不想花费精力在这上面.

因此,如果您致力于拥有一个方法联合,您将需要手动annotate the parameters个,并明确说明您期望它具有什么类型.


但看起来你并不真的想要unions .转而为

type TItem = { hello: string } | string;

您希望Optional<TItem>的计算结果为单一对象类型{get: (item: TItem) => string},对吗?如果是这样的话,我们所需要做的就是使用文档中提到的作为单个元素的WRAP-tuple-type技术禁用分布式对象类型:

type Optional<T> = [T] extends [string]
  ? { get?: (item: T) => string }
  : { get: (item: T) => string };

现在,在对T进行手术之前,Optional<T>永远不会将T分割成联合的碎片.现在,您将获得您要查找的上下文类型:

const obj: Optional<TItem> = {
  get: item => typeof item === 'string' ? item : item.hello // okay
};

Playground link to code

Typescript相关问答推荐

TS 2339:属性切片不存在于类型DeliverableSignal产品[]上>'

TypeScript泛型参数抛出错误—?&#"' 39;预期"

找不到带名称的管道''

当使用`type B = A`时,B的类型显示为A.为什么当`type B = A时显示为`any `|用A代替?

Angular 行为:属性类型从SignalFunction更改为布尔

接口的额外属性作为同一接口的方法的参数类型'

为什么我的Set-Cookie在我执行下一次请求后被擦除

类型脚本`Return;`vs`Return unfined;`

部分类型化非 struct 化对象参数

限制返回联合的TS函数的返回类型

如何在typescript中为this关键字设置上下文

对象类型的TypeScrip隐式索引签名

KeyOf关键字在特定示例中是如何工作的

Select 类型的子项

有没有一种方法可以防止我的组件包在其中安装样式组件'; node 模块中的s目录

React-跨组件共享功能的最佳实践

是否使用类型将方法动态添加到类?

覆盖高阶组件中的 prop 时的泛型推理

如何确定单元格中的块对 mat-h​​eader-cell 的粘附(粘性)?

TS 条件类型无法识别条件参数