简体   繁体   English

TypeScript 可区分联合 - 在详尽的 If 语句之后分配之前使用的变量

[英]TypeScript Discriminated Union - Variable Used Before Assigned after Exhaustive If Statements

I am writing some code using TypeScript's discriminated union feature.我正在使用 TypeScript 的可区分联合功能编写一些代码。 I am exhaustively checking the "type" property for each type in an if-else if structure and assigning a variable using logic in each block.我正在详尽地检查if-else if结构中每种类型的“类型”属性,并使用每个块中的逻辑分配一个变量。 Then, I am returning the variable.然后,我返回变量。 However, I am getting an error about the returned variable being used before it is assigned.但是,我收到关于在分配之前使用的返回变量的错误。 The code follows this structure (this is a really simple example demonstrating the problem since my actual code is much more complex):代码遵循这种结构(这是一个非常简单的示例来演示问题,因为我的实际代码要复杂得多):

interface One
{
  num   : "one";
  value : string;
}

interface Two
{
  num   : "two";
  value : number;
}

interface SomeComplexObject
{
  // Complex properties
}

type Num  = One | Two;

function isOne(
  obj : Num
) : SomeComplexObject
{
  let complex : SomeComplexObject;

  if (obj.num === "one")
  {
    // Create a complex object with one set of parameters
  }
  else if (obj.num === "two")
  {
    // Create a complex object with a second set of parameters
  }

  return complex;
}

My first thought was to add a final else to throw an error saying that (in this case) the value for num is invalid, but since the other conditions are exhaustive, obj is of type never and cannot be used.我的第一个想法是添加一个 final else来抛出一个错误,说(在这种情况下) num的值是无效的,但是由于其他条件是详尽的,所以obj的类型是never并且不能使用。

I could throw a super generic error and be done with it, but I am wondering why the compiler thinks complex could be undefined but at the same time recognize that the conditions are exhaustive.我可以抛出一个超级通用的错误并完成它,但我想知道为什么编译器认为complex可能是未定义的,但同时认识到条件是详尽的。 Is there something I am missing?有什么我想念的吗?

Edit : My original example seems to have caused some confusion.编辑:我原来的例子似乎引起了一些混乱。 I updated it to hopefully be more representative of the actual problem.我对其进行了更新,希望能更能代表实际问题。

I handle these sorts of scenarios one of two ways.我以两种方式之一处理这类场景。 Usually go with the exhaustive switch.通常go用穷举开关。

interface One {
  num   : "one";
  value : string;
}

interface Two {
  num   : "two";
  value : number;
}

interface SomeComplexObject {
  // Complex properties
}

type Num = One | Two;

// Exhaustive Switch
function isOne(obj : Num) : SomeComplexObject {
    let complex: SomeComplexObject;

    switch (obj.num) {
        case "one":
            complex = {};
        case "two":
            complex = {};
    }

    return complex;
}

// Cast obj to any in `never` case
function isOne2(obj : Num) : SomeComplexObject {
    let complex: SomeComplexObject;

    if (obj.num === "one") {
        complex = {};
    } else if (obj.num === "two") {
        complex = {};
    } else {
        throw new Error(`Unknown object type ${(obj as any).num}`)
    }

    return complex;
}

Typescript Playground Typescript 游乐场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM