Typescript,检查是否至少提供一个

huangapple go评论45阅读模式
英文:

Typescript, check if at least one is provided

问题

我有以下简单的函数

function takeOneOfOrThrow(firstOptionalVariable: string | undefined, secondOptionalVariable: string | undefined) {
    let result: string;

    if (!firstOptionalVariable && !secondOptionalVariable) {
        throw new Error('both are undefined');
    }
    result = firstOptionalVariable ? firstOptionalVariable : secondOptionalVariable;
};

Playground链接:https://tsplay.dev/mxJoxw。

两个变量都是字符串或未定义的。第一个条件消除了两者都是未定义或空字符串的情况。因此,其中一个肯定是长度大于0的字符串。
为什么 TypeScript 还会报错,指出 Type 'string | undefined' is not assignable to type 'string'.?应该如何正确解决这个问题?

英文:

I have following simple function

function takeOneOfOrThrow(firstOptionalVariable : string | undefined, secondOptionalVariable : string | undefined) {
    let result : string; 

    if ( !firstOptionalVariable && !secondOptionalVariable) {
        throw new Error('both are undefined'); 
    } 
    result = firstOptionalVariable ? firstOptionalVariable : secondOptionalVariable; 
}; 

Link to playground : https://tsplay.dev/mxJoxw.

both variables are string or undefined. First if eliminates the case that both are undefined or empty strings. therefore one of them for sure is string of length > 0.
Why then typescript gives me error there Type 'string | undefined' is not assignable to type 'string'. > What is proper approach to this problem ?

答案1

得分: 1

编译器无法根据您的条件推断类型。

您的条件检查变量是否都是undefined,但即使其中一个不是,也无法推断它们的正确类型,因为将它们都设为string是没有意义的,因为这不是条件检查的内容。此外,编译器无法仅将其中一个推断为string,因为编译器无法在运行时之前知道哪一个不会为空。因此,当您尝试分配给变量时,变量之间没有关系,因此会出现错误。

其中一个可能的解决方案是使用非空断言操作符,就像其他答案建议的那样,但我建议避免使用它,因为如果函数体发生更改并且条件被移除,编译器不会引发任何错误。

最简单的替代方法是在两个变量都为空时设置默认值,假设由于条件不会达到默认值:

result = first ?? second ?? '';

或者,您可以使用if/else块:

function takeOneOfOrThrow(firstOptionalVariable: string | undefined, secondOptionalVariable?: string | undefined) {
    let result: string;

    if (!firstOptionalVariable && !secondOptionalVariable) {
        throw new Error('both are undefined');
    }
    else if (firstOptionalVariable) {
        result = firstOptionalVariable;
    } else if (secondOptionalVariable) {
        result = secondOptionalVariable
    }
}; 
英文:

The compiler is unable to infer types based on your condition.

Your condition checks whether both of the variables are undefined, however even if one of them is not, there is no way to infer the correct type for them since it doesn't make sense to make both of them just string because it's not what the condition checks. Also, the compiler can't infer just one of them as string since the compiler can't know until the runtime which one of them won't be empty. Thus, when you try to assign to variable there is no relation between variables and therefore you get the error.

One of the possible solutions is to use non-null assertion operator as the other answer suggests, however, I would recommend avoiding using it, since if the body of the function changes and the condition will be removed, the compiler won't raise any error.

The simplest alternative is to have a default value if both of the variables are empty, assuming that the default value won't be reached, because of the condition:

result = first ?? second ?? ''

Alternatively, you can use if/else blocks:

function takeOneOfOrThrow(firstOptionalVariable: string | undefined, secondOptionalVariable?: string | undefined) {
    let result: string;

    if (!firstOptionalVariable && !secondOptionalVariable) {
        throw new Error('both are undefined');
    }
    else if (firstOptionalVariable) {
        result = firstOptionalVariable;
    } else if (secondOptionalVariable) {
        result = secondOptionalVariable
    }
}; 

huangapple
  • 本文由 发表于 2023年6月22日 17:02:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530217.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定