如何解决使用通用约束时,类型缩小无法按预期工作
我有一种情况,泛型类型受到联合类型的约束,但我发现这样做不会使类型缩小以按预期工作。下面的代码片段显示了正在发生的事情。
function somefunc<T extends string | number>(input: T): T {
if (typeof input === "string") {
// expecting input to be of type "string"
// but input becomes of type T & "string"
input
} else {
// expecting input to be of type "number"
// but input becomes of type T extends string | number
input
}
}
如果我取消泛型,只将函数参数注释为 string | number
就可以了,但对于我的用例,我需要有泛型约束。
编辑
用例基本上是尝试将其与条件类型一起使用。基本上我想让结果类型成为取决于输入类型的条件类型。所以当输入类型为number
时,结果也是number
,当输入类型为string
时结果也变成string
。基本上是这样的:
type Result<T> = T extends string ? string : number
function somefunc<T extends string | number>(input: T): Result<T> {
if (typeof input === "string") {
// expecting input to be of type "string"
// but input becomes of type T & "string"
input
} else {
// expecting input to be of type "number"
// but input becomes of type T extends string | number
input
}
}
我可能遗漏了一些东西,但问题是,我如何拥有基于联合的泛型约束并按照我的预期进行类型缩小工作。在上面的代码中,这意味着,在 if
分支中,input
变为类型 string
而在 else
分支中,它变为 number
(或在至少它变成了 T & number
)
** 编辑 **
我能够使用函数重载来实现我想要的。我只是想知道使用泛型和条件类型是否可以实现同样的事情。
解决方法
未缩小的原因在this answer
中说明正确缩小类型的黑客方法:
type Result<T> = T extends string ? string : number;
function somefunc<T extends string | number>(input: T): Result<T> {
const inputNarrowed: string | number = input;
if (typeof inputNarrowed === "string") {
inputNarrowed; // string
} else {
inputNarrowed; // number
}
return inputNarrowed as Result<T>;
}
重载+条件泛型的替代解决方案(我更喜欢)
type Result<T> = T extends string ? string : number;
function somefunc<T extends string | number>(input: T): Result<T>;
function somefunc(input: string | number) {
if (typeof input === "string") {
input; // string
} else {
input; // number
}
return input;
}
const str = somefunc("string"); // string
const num = somefunc(1); // number
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。