我正在尝试一个非常基本(人为)的条件类型函数,但遇到了意外错误:
function test<
T
>(
maybeNumber: T
): T extends number ? number : string {
if (typeof maybeNumber === 'number') {
return maybeNumber // Type 'T & number' is not assignable to type 'T extends number ? number : string'.
}
return 'Not a number' // Type '"Not a number"' is not assignable to type 'T extends number ? number : string'.
}
我认为这是一个非常简单的条件类型用法,所以不确定发生了什么。有什么想法吗?
我认为您在错误的位置定义了返回类型:
function test<T extends number | String>(maybeNumber: T) {
if (typeof maybeNumber === 'number') {
return maybeNumber
}
return 'Not a number'
}
正确答案和当前的变通方法(在写作时):
type MaybeNumberType<T extends number | string> = T extends number
? number
: string;
function test<T extends number | string>(
maybeNumber: T,
): MaybeNumberType<T> {
if (typeof maybeNumber === 'number') {
return <MaybeNumberType<T>>(<unknown>maybeNumber);
}
return <MaybeNumberType<T>>(<unknown>'Not a number');
}
test(3); // 3
test('s'); // Not a number
潜在的问题是TypeScript的编译器没有通过控制流分析缩小泛型类型变量的类型。当您检查(typeof maybeNumber==="数字")
时,编译器可以将值maybeNumber
缩小到数字
,但它不会将类型参数T
缩小到数字
。因此,它不能验证将数字
值分配给返回类型T扩展数字是否安全?数字:字符串
。编译器将不得不执行一些它目前不做的分析,例如“好吧,如果typeof maybeNumber==="数字"
,我们仅从maybeNumber
的类型推断T
,那么在这个块内我们可以将T
缩小为number
,因此我们应该返回类型为number的值扩展数字?数字:字符串
,又名数字
。但这并没有发生。
对于具有条件返回类型的泛型函数来说,这是一个相当棘手的问题。关于这一点的规范性开放GitHub问题可能是microsoft/TypeScript#33912,但还有许多其他GitHub问题,这是主要问题。
这就是“为什么这行不通”的答案?
如果您对重构不感兴趣,那么可以忽略其余部分,但是知道在这种情况下应该做什么,而不是等待语言的更改,这可能仍然是有益的。
这里维护调用签名的最直接的解决方法是使函数成为单个签名重载,而实现签名不是泛型的。这实质上放松了实现内部的类型安全保证:
type MyConditional<T> = T extends number ? number : string;
type Unknown = string | number | boolean | {} | null | undefined;
function test<T>(maybeNumber: T): MyConditional<T>;
function test(maybeNumber: Unknown): MyConditional<Unknown> {
if (typeof maybeNumber === 'number') {
const ret: MyConditional<typeof maybeNumber> = maybeNumber;
return ret;
}
const ret: MyConditional<typeof maybeNumber> = "Not a number";
return ret;
}
在这里,我已经尽我所能,通过使用一个临时ret
变量(注释为MyConditional)来保证类型安全
function test2<T>(maybeNumber: T): MyConditional<T>;
function test2(maybeNumber: any): string | number {
if (typeof maybeNumber === 'number') {
return maybeNumber;
}
return "Not a number";
}
好吧,希望这会有帮助;祝你好运
操场连结至守则
我正在尝试创建一个通用函数,它接受一个,并返回一个对象,该对象包含公共基类型的属性以及特定类型的默认值。出于某种原因,如果没有编译器的抱怨,我无法让它工作。我不确定问题出在哪里,但是 我怀疑这可能是将类型定义为条件类型的方式。我尝试过以各种方式重新定义我的类型,但没有成功,所以我怀疑我要么错过了一些明显的东西,要么没有类型断言是不可能的。 以下是我的类型: 以下是我的通用函数: 产生以下错误: 类
我想通过TypeScript泛型定义函数返回类型。所以R可以是我将定义的任何东西。 <代码>。。。许诺 错误:(29,9)TS2322:类型“字符串”不可分配给类型“R”。“字符串”可分配给类型“R”的约束,但“R”可以用约束“{}”的不同子类型实例化。
我试图创建一个返回泛型类型参数的方法。 我有一个类车辆订单扩展抽象类订单。在类订单中,我创建了一个抽象方法接收HiredObject。这个方法不会接收任何参数,并将返回一个泛型。 我在VehicleOrder类中实现了这个方法,并将其设置为返回类参数vehicle。 问题是,当我实例化一个新的VeilceOrderorororororororororororororderororororororo
(沙盒) 获取此错误: 类型“number”不可分配给类型“T”“number”可分配给“T”类型的约束,但“T”可以用约束{}的不同子类型实例化。(2322)输入。ts(1,26):预期类型来自此签名的返回类型。 我希望typescript能够自动推断T为数字,然后直接使用它。为什么它在抱怨?写这样的东西的正确方法是什么?谢谢
假设我想写一个函数,它可以接受一个参数,这个参数可以是null类型,也可以是非null类型。如果参数不可为null,则返回类型也应不可为null。类似地,如果参数是可空类型,那么返回类型也应该是可空类型。 以下是我为实现这一职能所做的尝试: 函数签名似乎是正确的,因为它在调用站点上实现了所需的行为,例如: 即返回类型确实由参数类型以正确的方式确定。 然而,我的问题在于函数的实现。如果不将返回值强制
对于一堆带有泛型的包装类,我的继承结构遇到了一些麻烦。这基本上是结构: 这将与当前代码一起编译和工作,但是,这似乎很危险。如果调用方像这样使用这个方法:,它将很好地编译,但是如果findMiddle尝试返回SubBWrapper,则在运行时会有一个ClassCastException。我以为行得通却行不通的是: 所以我的问题基本上是,有没有正确的方法来编写编译、运行并遵循最佳实践的方法findMi