typescript 泛型在存在联合且涉及条件类型时推断文本类型

qv7cva1a  于 2023-02-10  发布在  TypeScript
关注(0)|答案(2)|浏览(138)

我偶然发现了这种不一致的行为:
条件句本身就很好用:

class FormControl<T> {
  constructor(t:T extends undefined ? never : T) {}
}
const a = new FormControl('');
//    ^? FormControl<string> // OK

单独的联合也可以:

class FormControl2<T> {
  constructor(t:T|string) {}
}
const b = new FormControl2("");
//    ^? FormControl<string> OK

当两个union+conditional组合时:

class FormControl3<T> {
  constructor(t:T extends undefined ? never : T|string) {}
}
const c = new FormControl3(""); 
//    ^? FormControl<""> // Too narrow :(

在第三种情况下,a如何获得更宽的string推断类型?我正在寻找加宽推断,而不是每次都指定正确的类型。
Playground

xoefb8l8

xoefb8l81#

经过一番阅读,它可能与typescript对文本类型的使用有关,如中所示:https://github.com/microsoft/TypeScript/pull/10676
在调用表达式的类型参数推断期间,如果满足以下条件,则将为类型参数T推断的类型加宽为其加宽的文本类型:

  • 对T的所有推断均针对特定参数类型内T的顶级发生率,以及
  • T没有约束或其约束不包括基元或文本类型,并且
  • T在推理过程中是固定的,或者T没有出现在返回类型的顶层。
0md85ypi

0md85ypi2#

这是一个非常有趣的问题!
恐怕我不知道为什么会发生这种事尽管我花了比我愿意承认的更多的时间试图弄清楚。
根据上一个问题,您可以通过执行以下操作强制输入字符串:

const c = new FormControl3("" as string); 
//    ^? FormControl<string>

或者,您也可以执行以下操作:

const c = new FormControl3<string>(""); 
//    ^? FormControl<string>

相关问题