Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript typescript中的方法参数和返回类型重写_Javascript_Typescript - Fatal编程技术网

Javascript typescript中的方法参数和返回类型重写

Javascript typescript中的方法参数和返回类型重写,javascript,typescript,Javascript,Typescript,我不想在抽象类中描述一个抽象方法,它可以接受number或string,也可以返回number或string; 我使用|符号告诉方法,它的参数和返回类型可能因字符串和数字而异。 然后我创建了两个类b和c,它们是从抽象类a扩展而来的,并试图覆盖方法test(),而不带参数和返回类型变化。 接下来,我将声明变量x哪种类型可以类似于b或c类,并根据随机语句创建其中一个类的instance。 最后,我尝试调用test()方法,但TS编译器给出了下面描述的错误 abstract class a {

我不想在抽象类中描述一个抽象方法,它可以接受
number
string
,也可以返回number或string; 我使用
|
符号告诉方法,它的参数和返回类型可能因字符串和数字而异。
然后我创建了两个类
b
c
,它们是从抽象类
a
扩展而来的,并试图覆盖方法
test()
,而不带参数和返回类型变化。
接下来,我将声明变量
x
哪种类型可以类似于
b
c
类,并根据随机语句创建其中一个类的instance。
最后,我尝试调用
test()
方法,但TS编译器给出了下面描述的错误

abstract class a {
    abstract test(x: string | number): string | number;
}

class b extends a {
    test(x: number): number {
        return x;
    }
}


class c extends a {
    test(x: string): string {
        return x;
    }
}

let x: b | c;


if (Math.random() > 0.5) {
    x = new b()
} else {
    x = new c()
};

x.test(1)
以下是TS编译器的错误:

无法调用其类型缺少调用签名的表达式。类型“((x:number)=>number)|((x:string)=>string)”没有兼容的呼叫签名。
(属性)测试:((x:number)=>number)|((x:string)=>string)

也许我使用了错误的方法,或者我误解了TS文档,如果是这样的话,请您为我指出实现目标的更好方法。

为糟糕的类名和缺少任何“fiddle”而抱歉-我找不到任何突出TS编译器错误的js游乐场网站,因此我建议官方

您将x声明为b或c,然后尝试通过使其仅为b或c来重新定义它(据我所知,但我的理解有限) 根据您提供的编辑器,以下代码仍然有效:

abstract class a {
abstract test(input: number | string )   
}

class b extends a {
    test(x: string) {
        return x;
    }
}

class c extends a {
    test(x : number) {
        return x;
    }  
}

let x//: b | c;

if (Math.random() > 0.5) {
    x = new b()
} else {
    x = new c()
}

x.test(1)

当您在if块中创建类的实例时,typescript编译器无法确定x将是哪种类型。这是可以的,但问题是,然后您尝试用一个数字调用测试函数,而这仅在类型为b时才可能。由于编译器认为x有可能是c类型的,因此会出现错误

您需要向编译器保证,当您调用test时,您调用的函数将始终与提供的参数匹配

您可以:

  • 更改调用签名,使两者都接受任何类型,这样编译器就不在乎调用哪种方法:

    class b extends a {
        test(x: any) {
            return x;
        }
    }
    
    class c extends a {
        test(x : any) {
            return x;
        }  
    }
    
  • 调用if块中的方法:

    if (Math.random() > 0.5) {
        x = new b();
        x.test(1);
    } else {
        x = new c();
        x.test('1');
    }
    
  • 方法调用的Typeguard:

    if (x instanceof b)
        x.test(1);
    else if(x instanceof c)
        x.test('1');
    
  • 查看有关活接头类型和护板的手册:

    编辑: 对您的建议是,不必在每次调用时都进行类型保护,而是在方法本身中进行类型检查。这样做的缺点是,可以使用不正确的参数调用该方法,而不会从编译器得到警告。下面是一个这样的例子:

    abstract class a {
        protected abstract internal(x: any): any;
    
        public test(x: string | number): string | number {
            return this.internal(x);
        }
    }
    
    class b extends a {
        protected internal(x) {
            if (typeof x === "number") 
                return x;
            else
                throw new Error("Invalid argument");
        }
    }
    
    
    class c extends a {
        protected internal(x) {
            if (typeof x === "string")
                return x;
            else
                throw new Error("Invalid argument");
        }
    }
    
    let x: b | c;
    
    
    if (Math.random() > 0.5) {
        x = new b();
    } else {
        x = new c();
    }
    
    x.test(1);
    

    是的,这很有帮助,但是我得到了关于implict
    any
    类型的错误,因为我的tsconfig中有
    “noImplicitAny”:true
    字符串。我知道我可以删除它,或者用
    任何
    类型声明varaible
    x
    。我想要显式的变量声明-这可能吗?谢谢。你能告诉我我是否每次都需要typeguard我的方法调用,或者有一些“一次性使用”的解决方案吗?在不了解更多关于你试图完成的事情的情况下,精确回答有点困难,但我用一个示例编辑了我的答案,你可以尝试一下。