【问题标题】:Typescript: downcast on "this" is not possible打字稿:不可能对“这个”感到沮丧
【发布时间】:2018-04-27 10:28:51
【问题描述】:

在以下示例中,TypeScript 编译器不允许将 this 直接转换为 Child。实际上,可以使用中间变量 temp 或双重转换,如注释行所示。 这是一个错误还是有任何合乎逻辑的解释? playground的链接

    class Parent {
        prop: string = null;
        castToChild(): Child{
            let temp: Parent = this;
            return this as Child;
            //return temp as Child;
            //return this as Parent as Child;
        }
    }
    class Child extends Parent
    {
        otherProp: string = null;
    }

【问题讨论】:

    标签: typescript casting


    【解决方案1】:

    您不能直接将Parent 转换为Child,因为编译器无法知道您的Parent 实例确实是Child。使用类型保护而不是强制类型转换:

    class Parent {
        prop: string|null = null;
        isChild(): this is Child {
            return (this as any).otherProp !== undefined;
        }
    }
    class Child extends Parent
    {
        otherProp: string|null = null;
    }
    
    function test(p: Parent) {
      if (p.isChild()) {
        console.log(p.otherProp);
      }
    }
    

    在受保护的if 内部,编译器现在知道pChild,在它外部p 仍然只是Parent

    或者更好的是,覆盖子类中的守卫,您可以完全避免进行任何类型转换:

    class Parent {
        prop: string|null = null;
        isChild(): this is Child {
            return false;
        }
    }
    class Child extends Parent
    {
        otherProp: string|null = null;
        isChild(): this is Child { return true; }
    }
    
    function test(p: Parent) {
      if (p.isChild()) {
        console.log(p.otherProp);
      }
    }
    

    您是对的,但是我没有回答这个问题是 Typescript 作者的错误还是故意的。我的猜测是他们试图捕捉可能的错误,但我还没有设法找到可以确认或否认这种确切行为的解释。

    使原始代码工作的另一种方法是在 castToChild 方法中明确告诉 typescript this 的类型:

    class Parent {
        prop: string|null = null;
    
        castToChild(this: Parent): Child{
            return this as Child;
        }
    }
    class Child extends Parent
    {
        otherProp: string|null = null;
    }
    
    function foo() {
      let p: Parent = new Child();
      let c = p.castToChild();
      console.log(c.otherProp);
    }
    

    这仍然只是做双重演员,但可能看起来更干净一些。然而,它仍然显示出行为的奇怪之处,因为没有显式 this 参数 thisParent 类型但不能直接转换,使用显式参数可以转换它。

    【讨论】:

    • 抱歉,我认为您的解决方案过于复杂。我使用中间变量或使用双重转换的解决方法要短得多,并且不需要额外的代码。但它们只会产生不必要的句法噪音。我同意编译器不知道 Parent 确实是 Child,但这正是我进行强制转换的原因 - 告诉 更了解它。
    • 有趣的观点。当然,使用 typescript 的目的是因为有时你不知道更好,如果你犯了错误,编译器会告诉你。如果你总是比编译器更了解,为什么不直接使用 javascript 而完全不用担心这些类型?
    • 很抱歉,如果我的回答以某种方式冒犯了您,这肯定不是我的本意。但是您的建议仍然不是我问题的答案:“为什么 TS 编译器接受强制转换为双重强制转换或使用中间变量,而不是直接方式?”用两个步骤而不是一个步骤走同样的路就是我所说的“句法噪音”
    • 没有冒犯。我已经扩展了我的答案,虽然它仍然没有回答你问题的基本“它是一个错误”部分。
    猜你喜欢
    • 1970-01-01
    • 2016-07-07
    • 2011-05-29
    • 2011-01-26
    • 1970-01-01
    • 2014-07-21
    • 2013-06-06
    • 1970-01-01
    相关资源
    最近更新 更多