TypeScript在通过if检查后不会检测可选字段是否定义

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

Typescript does not detect optional field is define after check by if

问题

  async patchMultiple(expenses: PatchExpenseDto[]) {
    const currentExpenses: Required<PatchExpenseDto>[] = []
    const newExpenses: PatchExpenseDto[] = []

    expenses.forEach(expense => {
      if (expense._id) {
        expense._id
        currentExpenses.push(expense) // typescript在这里报错
      } else {
        newExpenses.push(expense)
      }
    })
  }

经过检查,即使在if(expense._id)后,typescript依然报错:

类型“PatchExpenseDto”的参数不能赋给类型“Required<PatchExpenseDto>”的参数。
属性“_id”的类型不兼容。
类型“ObjectId | undefined”不能赋给类型“ObjectId”。
类型“undefined”不能赋给类型“ObjectId”。
英文:

I have the code like bellow

  async patchMultiple(expenses: PatchExpenseDto[]) {
    const currentExpenses: Required&lt;PatchExpenseDto&gt;[] = []
    const newExpenses: PatchExpenseDto[] = []

    expenses.forEach(expense =&gt; {
      if (expense._id) {
        expense._id
        currentExpenses.push(expense) // typescript throw error here
      } else {
        newExpenses.push(expense)
      }
    })
  }

After check with if(expense._id) typescript still throw the error

Argument of type &#39;PatchExpenseDto&#39; is not assignable to parameter of type &#39;Required&lt;PatchExpenseDto&gt;&#39;.
  Types of property &#39;_id&#39; are incompatible.
    Type &#39;ObjectId | undefined&#39; is not assignable to type &#39;ObjectId&#39;.
      Type &#39;undefined&#39; is not assignable to type &#39;ObjectId&#39;

答案1

得分: 1

Typescript理解该属性实际上存在,但无法推断使用if条件的对象的类型。

您可以使用类型保护来解决此问题:

interface PatchExpenseDto  {
  name : string;
  _id? : string;
}

function expenseIsCurrent(expense: PatchExpenseDto): expense is Required<PatchExpenseDto> {
  return expense._id !== undefined;
}

const patchMultiple = (expenses: PatchExpenseDto[]) => {
  const currentExpenses: Required<PatchExpenseDto>[] = []
  const newExpenses: PatchExpenseDto[] = []

  expenses.forEach(expense => {
    if (expenseIsCurrent(expense)) {
      currentExpenses.push(expense) // typescript throw error here
    } else {
      newExpenses.push(expense)
    }
  })
}

Playground

英文:

Typescript understands that the property in fact exists, but it cannot infer the type of the object using the if condition.

You can use a typeguard to get past this:

interface PatchExpenseDto  {
name : string;
_id? : string;
}
function expenseIsCurrent(expense: PatchExpenseDto): expense is Required&lt;PatchExpenseDto&gt; {
  return expense._id !== undefined;
}




const patchMultiple = (expenses: PatchExpenseDto[]) =&gt; {
    const currentExpenses: Required&lt;PatchExpenseDto&gt;[] = []
    const newExpenses: PatchExpenseDto[] = []

    expenses.forEach(expense =&gt; {
      if (expenseIsCurrent(expense)) {

        currentExpenses.push(expense) // typescript throw error here
      } else {
        newExpenses.push(expense)
      }
    })
  }

Playground

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

发表评论

匿名网友

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

确定