TypeScript 根据使用的参数推断返回类型

Can*_*ğlu 6 type-inference inferred-type typescript typescript3.0

我不确定这是否是在不同的术语下提出的。我有一个带有两个参数的函数,其中两个参数都可以(独立地)为numberstringundefined。返回的值静态地保证也是这两个参数之一:

export function wideNarrow(wide:number|string|undefined, 
                           narrow:number|string|undefined){
    return isNarrowScreen() ? narrow : wide;
}
Run Code Online (Sandbox Code Playgroud)

在我的应用程序的某些部分,我将两个数字传递给该函数:

wideNarrow(8, 0);

然而,推断的返回类型是string|number,这显示了数值运算的错误:

const extendedAreaHeight = 26;
const baseY = extendedAreaHeight + wideNarrow(8, 0);
Run Code Online (Sandbox Code Playgroud)

Operator '+' cannot be applied to types '26' and 'string | number'.ts(2365)

Object is possibly 'undefined'.ts(2532)

可以静态地推断出这个特定的调用总是返回一个数字,为​​什么 TypeScript 没有检测到它并且仍然认为可能返回一个字符串或未定义,以及如何在不破坏现有功能的情况下修复它(例如我可以返回undefinedstringstringnumberundefinednumber以及这些的任意组合(在我称为该函数的其他地方)?

我使用的是 TypeScript 3.5.2/Vscode 1.36.1。

Can*_*ğlu 5

正如托马斯所建议的(我同时发现的),使用两个具有相同签名的类型参数可以解决问题:

export function wideNarrow
  <T=number|string|undefined,
   K=number|string|undefined> 
   (wide:T, narrow:K){
  return isNarrowScreen() ? narrow : wide;
}
Run Code Online (Sandbox Code Playgroud)

使用两种确切类型而不是一种的原因是它们可能不同,正如我在问题中所述。如果我只是T在没有Kwide类型narrow的情况下制作它T,它会强制两者widenarrow相同类型(例如,两者number),而我有时需要它们为不同类型(例如,宽string但窄number)。

注意:如果有人真的想知道在什么情况下我需要这种方式,我将使用它来填充我的 React Native 应用程序中的样式表,其中某些样式元素对numbers 例如(width: 100100 点宽)或strings都非常满意(例如width: '50%')水平填充容器的一半)。