类型为'string|undefined'不可分配给类型为'"无标题的"|nu



我对TypeScript的类型推理有些理解。我认为这应该是有效的,不需要我指定T:的类型

export const deflt = <T>(val: (T | undefined | null), defaultVal: T): T => {
if (val === undefined || val === null) {
return defaultVal;
}
return val;
}
function maybeLabelName(name: string | undefined) {
return deflt(name, 'untitled');
}

对deflt的调用失败,并出现以下错误:

Argument of type 'string | undefined' is not assignable to parameter of type '"untitled" | null | undefined'.
Type 'string' is not assignable to type '"untitled" | null | undefined'. [2345]

我可以通过将deflt调用更改为以下之一来修复它:

// Option 1:
return deflt<string>(name, 'untitled');
// Option 2:
const s: string = 'untitled';
return deflt(name, s);

TypeScript不应该自动推断string类型吗?

在这种情况下,typescript推断T的方式有点奇怪。因为您指定了常量'untitled',所以编译器会将T推断为字符串文字类型'untitled',因为这是从中推断T的最简单的站点。然后,它将对照字符串文字类型检查另一个参数,并发现string不可分配给'untitled'。解决方法是在通过添加与{}:的额外交集来推断T时降低第二个参数的优先级

export const deflt = <T>(val: (T | undefined | null), defaultVal: T & {} ): T => {
if (val === undefined || val === null) {
return defaultVal;
}
return val;
}
function maybeLabelName(name: string | undefined) {
return deflt(name, 'untitled'); // T is string now
}

另一个解决方案(如果不能更改原始函数(是显式断言untitledstring,这基本上是您已经尝试过的。

function maybeLabelName(name: string | undefined) {
return deflt(name, 'untitled' as string); // T is string now
}

当您使用泛型时,可以有两种不同的方法来"生成"参数。

以您的案例为例:

const deflt = <T>(val: (T | undefined | null), defaultVal: T): T

如果使用:deflt<string>(a, b),则强制astring | undefined | null,强制bstring

如果使用:deflt(a: string, b: "untitled"),则转发器将"untitled"理解为常量,而不是字符串。因此,b将是"untitled"类型,从而使得T"untitled"类型。由于您使用的是string类型的a,因此编译器无法将string强制转换为"untitled"

解决方案已经由@Titian Cernicova Dragomir回答提供

您已将deflt声明为泛型函数,但已将其用作正则函数

const deflt = <T>(val: (T | undefined | null), defaultVal: T): T => {
if (val === undefined || val === null) {
return defaultVal;
}
return val;
}
function maybeLabelName(name?: string) {
return deflt<typeof name>(name, 'untitled');
}

相关内容

最新更新