TypeScript 在通用的错误行为中缩小空字符串或false的行为是不正常的,

iq3niunx  于 6个月前  发布在  TypeScript
关注(0)|答案(2)|浏览(44)

🔎 搜索词

泛型,缩小,空字符串,false,假值

🕗 版本与回归信息

这是我尝试的每个版本的行为,但似乎在TS v4.2.3及更早版本中表现得稍微差一些。

⏯ Playground链接

https://www.typescriptlang.org/play?ts=5.5.0-dev.20240417#code/GYVwdgxgLglg9mABKSBGAPAFUQUwB5Q5gAmAzomCALYBGOATogD4UgA2bzi4xOwMYHMS7AAhm1I4uAcmkA+ABR4AXK1oMumAJSIA3gCgAkPRxQQ9JHmYsefAUIDc+gL76U0eEncAmLLgJEZGp0jCyUHFy2-ILCLGISUiyyiirBGizaekYmZhaIVgD8+YhyiAAMiEVWqgC01flOru6wCMjgEADMfviEJOSU6qGsETYkdjEi4pIy8kqqAyGaOgbGpuaWlYgAsqJQABYAdKI0pEo6qniN+voQCKRQ+fPUi6O80UKIALxtaAqyWk5bmB7ogAJ5fH4QbwKGodAE3O4PABeEPcHRhcIcQA

💻 代码

function func1<T extends number | null | undefined | false | ''>(x: number | T) {
	return x || undefined;
}
function func2<T extends number | null | undefined | false | ''>(x: number | T) {
	return x ? x > 0 ? x : -x : x;
}
function func3<T extends number | null | undefined | false | ''>(x: number | T) {
	return x ? Math.abs(x) : x;
}

const x: number | undefined = func1('');
const y = func2(-3);
const z = func3(-3);

🙁 实际行为

func1的推断返回类型可以包含false'',取决于T。这是错误的,因为x || undefined永远不会导致false'',因此不应出现在结果类型中。
func2无法通过类型检查:Operator '>' cannot be applied to types 'number | NonNullable<T>' and 'number'.。这是错误的,因为真值检查应该将x缩小到number。(请注意,func3之所以能够通过类型检查,是因为Math.abs的签名似乎提供了补充信息,可以将x缩小到number。)

🙂 预期行为

func1的推断返回类型应该是number | undefined,无论T如何。
func2应该能够通过类型检查,已经将number缩小为x1m20n20,真值检查将其缩小为x1m20n20。

关于问题的附加信息

如果不使用泛型定义函数,所有函数都“正确”地工作,但这还不够,因为无论如何参数类型,func2func3的返回类型始终是number | null | undefined | false | ''
我实际的使用场景是创建将数字输入转换并传播假值的函数。我已经在使用需要缩小的地方使用类型Assert来解决这个问题。

bttbmeg0

bttbmeg01#

TS没有"T的真值"或"所有真值"的类型级表示,因此在任何需要写下类型的点上,最佳选择是NonNullable<T>,它是一个声音但不完整的超集(当它不应该包括''时)。

avkwfej4

avkwfej42#

但是,从联合类型中提取或排除假值类型似乎并不那么麻烦,就像NonNullable排除null和undefined并在这种情况下使用它们一样。如果T包括number,那么两个分支都必须包括number,因为没有NaN类型,但我认为你可以用Extract和Exclude完成这部分工作。
当然,我不知道这个改变涉及到的所有内容,所以这可能是一个困难的要求。

相关问题