代码之家  ›  专栏  ›  技术社区  ›  Peter V. Mørch

为什么这会发出打字警告?

  •  0
  • Peter V. Mørch  · 技术社区  · 5 年前

    needsString(var1) 在这个.tsx组件中,是否给出警告,而不是第一次或第三次调用?如果我把代码改成 var2 var1 (我认为它们有完全相同的类型),我没有收到警告。有什么好处?

    import { useParams } from "react-router-dom";
    
    const DeleteTeams2 = ({ var2 } : { var2: string | undefined})=> {
        // use var here so that var1 and var2 get exactly the same types
        var { var1 } = useParams();
    
        function needsString(str : string) : string {
            return "hello";
        }
    
        // I can tell typescript that var1
        // definitely is non-null with an if statement
        if (! var1)
            throw new Error("bad, bad varN");
    
        // This call is warning-free
        needsString(var1);
    
        // But JSX doesn't know that var1 is non-null for some reason...
        return (
            <div
                onClick={() => {
                    // I get a warning from this!
                    needsString(var1);
                }}
            >
                { needsString(var1) }
            </div>
        )
    }
    

    ,它们似乎都有相同的类型: var varN: string | undefined

    由于if语句,我希望 string 在if语句之后。事实上,这是为了 变量2 变量1 .

    但我接到一个警告 需要字符串(var1)

    TypeScript error in /path/to/foobar.tsx(146,29):
    Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
      Type 'undefined' is not assignable to type 'string'.  TS2345
    
        144 |             onClick={() => {
        145 |                 // I get a warning from this!
      > 146 |                 needsString(var1);
            |                             ^
        147 |             }}
        148 |         >
        149 |             { needsString(var1) }
    

    编辑:删除对的引用 Non-null assertion operator 因为我没有使用非空断言运算符,正如一些注释所指出的那样。

    1 回复  |  直到 5 年前
        1
  •  2
  •   Community CDub    4 年前

    问题是这里的代码:

    onClick={() => {
      // I get a warning from this!
      needsString(var1);
    }}
    

    if (! var1)
      throw new Error("bad, bad varN");
    
    // This call is warning-free
    needsString(var1);
    

    此外, var1 是可变引用,所以从TypeScript的角度来看 在检查它是否为空和实际使用它之间进行切换。例如,考虑以下示例代码:

    //it's populated
    var myVar = "hello";
    
    //verify it's populated
    if(!myVar) throw Error("WRONG!");
    
    //absolutely positively `myVar` is populated
    
    //set this to execute later
    setTimeout(() => console.log("myVar", myVar));
    
    //change it
    myVar = undefined;

    变量1 可以 useParams() 函数返回类型为的对象

    { [K in keyof Params]?: string | undefined; }
    

    也就是说 变量1 string | undefined . 如果 值更改(TypeScript无法确定是否更改),然后它可以看到 undefined

    使用 const

    您可以简单地将其声明为 const { var1 } ( Playground Link string 只有当它确保编译器不会在声明和用法之间更改它时。

    类型断言

    或者,显式地将类型设置为only 一串 : var { var1 } = useParams() as { var1: string }; Playground Link . 编译器会接受的 也许 吧 当然 这种情况就是这样,否则您可能会得到一个TypeScript编译器看不到的运行时错误(因为您故意“盲”了它)

    常数 只是在检查之后

    不管什么原因,你可以改变它或者其他任何东西,然后你可以做你的正常检查

    if (! var1)
      throw new Error("bad, bad varN");
    
    const checkedVar1 = var1;
    
    /* ... */
    
    onClick={() => {
      // I get a warning from this!
      needsString(checkedVar1);
    }}
    

    Playground Link

    这仍然有效,并将满足 checkedVar1 (我想你应该给它起个更合理的名字)在被指定一个绝对是字符串的东西和它被实际使用的时间之间没有变化。