为什么TypeScript没有';在重新声明变量时,请不要推断正确的类型

为什么TypeScript没有';在重新声明变量时,请不要推断正确的类型,typescript,Typescript,我写的代码有点像这样: function helloWorld(customName: string) { return `Hello, ${customName}`; } const myName: string | null = null; const isValidName = myName !== null; if (isValidName) { console.log(helloWorld(myName)); } 如果您这样做,您将看到TypeScript会抱怨类型为“n

我写的代码有点像这样:

function helloWorld(customName: string) {
  return `Hello, ${customName}`;
}

const myName: string | null = null;
const isValidName = myName !== null;

if (isValidName) {
  console.log(helloWorld(myName));
}
如果您这样做,您将看到TypeScript会抱怨类型为“null”的
参数不能分配给类型为“string”的参数。


但情况如何?该代码仅在
isValidName
为真时运行,并且
isValidName
只能在
myName
不为
null
时才为
true
。因此,
myName
在这里是一个
字符串。为什么这不起作用?

据我所知-您正在存储
myName!==null
进入变量
isValidName
强制执行类型脚本,以在运行时检查该值并进行适当的操作(因此调用
helloWorld(myName)
似乎是非法的,因为
isValidName
在运行时可能是
true
false

但是,如果您将支票更改为

if (myName !== null) {
  console.log(helloWorld(myName));
}

TypeScript将能够检测到在这些情况下,
myName
的唯一可能类型可以是
字符串。

按照您编写的方式,TypeScript会看到
isValidName
是一个
布尔值
常量,就是这样

<>你,代码作者,知道ValueNoest的值表明了关于<代码> MyNAME< /C>的值,但是Type Script不考虑这两个变量之间的关系。

您想要的是让您的
if
语句使用。本质上,类型保护是在运行时计算的布尔值,它取决于
myName
的值,布尔值是
true
还是
false
提供了一些缩小
myName
类型定义范围的信息

正如@falinsky指出的,
myName!==如果在
if
语句的条件内使用null,则可以将其用作类型保护。它说,“如果这是
true
,那么
myName
就不是
null

您还可以创建
isValidName
,作为检查名称并确定其为字符串的函数

const isValidName = (name: string | null): name is string => {
  return name !== null;
}

if (isValidName(myName)) {
  console.log(helloWorld(myName));
}

如果您想在
isValidName
中存储窄唐宁的结果以供进一步使用,并且不想重新计算,可以创建如下实用函数

/**
*@param a是预计算的结果
*@param\u b要缩小的变量
*@template T当'a'为真时,''u b'将缩小到的类型
*/
函数类型检查(a:布尔,_b:任意):_b是T{
归还
}
像这样使用

if(类型检查(isValidName,myName)){
console.log(helloWorld(myName));//此处为字符串
}否则{
console.log(myName)//此处为null
}

这在计算长表达式(如

if(
Islone可用容量(馈送)&&
(isAvailableCapacitySubbeamPath(链路)| | IsAvailableCapacityConnectionTyleGPath(链路))&&
toAvailableCapacityKey(feed.availableCapacity)==link.availableCapacityKey
) {
//做点什么
}
//剪断。。。。
//还有代码吗
如果(
Islone可用容量(馈送)&&
(isAvailableCapacitySubbeamPath(链路)| | IsAvailableCapacityConnectionTyleGPath(链路))&&
toAvailableCapacityKey(feed.availableCapacity)==link.availableCapacityKey
) {
//做点别的
}
它可以很容易地被替换为

const isValidFeed=islonavailablecapacity(feed)&&
(isAvailableCapacitySubbeamPath(链路)| | IsAvailableCapacityConnectionTyleGPath(链路))&&
toAvailableCapacityKey(feed.availableCapacity)==link.availableCapacityKey
if(类型检查(isValidFeed,feed)){
//做点什么
}
//剪断。。。。
//还有代码吗
if(类型检查(isValidFeed,feed)){
//做点别的
}

其他答案很好地解释了解决方法,但没有解释原因

简单的事实是,Typescript还不够复杂,无法理解多个因变量

很有可能在将来会增加这方面的功能。没有理由不这样做,但我想这很难

我希望有一天这会奏效,因为这也让我正在做的一些事情变得更简单