【问题标题】:TypeScript Conditional Return errorsTypeScript 条件返回错误
【发布时间】:2019-11-14 05:07:15
【问题描述】:

我有一个相对简单的函数,它应该根据给定的内容返回一个字符串或一个数字。我已经阅读了许多现有的问题,并且确实有函数重载工作,但我只想知道为什么所有返回行都会出现以下错误。

此函数应接受字符串或数字 defaultValue,然后返回该类型。所以如果 defaultValue 是一个字符串,它应该返回一个字符串。如果 defaultValue 是一个数字,它应该返回一个数字。

export const getMessageAttributes = <T extends string | number = string>(
    attributes: { [key: string]: { Name: string; Value: string } },
    name: string,
    defaultValue?: T,
): T extends string ? string : number => {
    const attribute = attributes[name];

    if (!attribute) {
        if (defaultValue === undefined)
            throw new Error(`MessageAttribute ${name} required but not found`);

        return defaultValue;
    }

    const value = attribute.Value;

    if (typeof defaultValue === 'number') return parseInt(value, 10);

    return value;
};

return defaultValue; 行,我收到此错误:

Type 'T' is not assignable to type 'T extends string ? string : number'.
  Type 'string | number' is not assignable to type 'T extends string ? string : number'.
    Type 'string' is not assignable to type 'T extends string ? string : number'.ts(2322)

return parseInt 行,我收到此错误:

Type 'number' is not assignable to type 'T extends string ? string : number'.ts(2322)

在最后的return value; 行,我收到此错误:

Type 'string' is not assignable to type 'T extends string ? string : number'.ts(2322)

如果有帮助,我正在使用 TypeScript 3.7.2 版。如前所述,我确实可以使用类型重载,从技术上讲,这可能会通过 2 个单独的函数(getStringMessageAttributegetNumberMessageAttribute)更好地解决,但实际上只是想扩展我的 TypeScript 知识并了解它当前失败的原因以及是否存在是一种解决方法。谢谢!

【问题讨论】:

  • 请考虑编辑上述代码以构成一个不依赖于外部类型的minimal reproducible example,以证明您的问题。这可能是 TypeScript 中的设计限制(请参阅 microsoft/TypeScript#22735),并且有一个未解决的问题建议可能的解决方法(请参阅 microsoft/TypeScript#33912
  • 谢谢,我编辑删除了一种外部类型。我也没有看到您发送的第一个链接,它给了我解决此问题的方法,我将发布该链接作为答案。仍然很好奇是否有更好的解决方案,但如果其他人遇到这种情况,希望这会有所帮助。

标签: typescript


【解决方案1】:

@jcalz 提供了一个链接来解释此处的错误: https://github.com/microsoft/TypeScript/issues/22735

相关部分是

为了让它工作,你必须明确地转换返回 值匹配返回类型注释,因为类型检查器 无法证明它总是正确的:

所以,使用它我最终得到了以下结果,它返回正确的类型而没有错误:

export const getMessageAttributes = <T extends string | number = string>(
    attributes: { [key: string]: { Name: string; Value: string } },
    name: string,
    defaultValue?: T,
): T extends string ? string : number => {
    const attribute = attributes[name];

    if (!attribute) {
        if (defaultValue === undefined)
            throw new Error(`MessageAttribute ${name} required but not found`);

        return (defaultValue as unknown) as T extends string ? string : number;
    }

    const value = attribute.Value;

    if (typeof defaultValue === 'number')
        return (parseInt(value, 10) as unknown) as T extends string
            ? string
            : number;

    return (value as unknown) as T extends string ? string : number;
};

不确定这是否是最好的方法,但它确实有效,因此希望在遇到类似情况时对其他人有所帮助。

【讨论】:

  • 有谁知道为什么它不能做出推断?这对我来说似乎很直接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 2020-05-31
  • 2021-09-28
  • 2022-06-30
相关资源
最近更新 更多