Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/239.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
Typescript继承并重载了函数的字符串文字参数_Typescript - Fatal编程技术网

Typescript继承并重载了函数的字符串文字参数

Typescript继承并重载了函数的字符串文字参数,typescript,Typescript,我目前正在尝试向一个非常依赖继承的库中添加一些类型。一般层次结构类似于: BaseWidget --> TextBox --> ValidationTextBox BaseWidget提供了一个名为getObj(name)的JS函数,该函数映射到TS中的getObj(name:string):any,有效地查找当前对象中名为\u get的函数,执行该函数并返回结果 这些“属性”在各个类上公开,并在类之间继承,以便ValidationTextBox可以访问TextBox上的所有属性。

我目前正在尝试向一个非常依赖继承的库中添加一些类型。一般层次结构类似于:

BaseWidget --> TextBox --> ValidationTextBox
BaseWidget提供了一个名为
getObj(name)
的JS函数,该函数映射到TS中的
getObj(name:string):any
,有效地查找当前对象中名为
\u get
的函数,执行该函数并返回结果

这些“属性”在各个类上公开,并在类之间继承,以便ValidationTextBox可以访问TextBox上的所有属性。我想知道是否可以添加类似于我在下面尝试的类型,而不必在每个类中重新定义重载

interface BaseWidget {
    getObj(name: string): any
}

interface TextBox extends BaseWidget {
    getObj(name: "B"): string
}

interface ValidationTextBox extends TextBox {
    getObj(name: "C"): boolean
    // getObj(name: "B"): string; // Adding this would make it compile, but obviously not ideal in the least
    // getObj(name: string): any // Adding this also compiles, but I lose type information for 'getObj("B")'
}

declare const obj: ValidationTextBox;
console.log(obj.getObj("B")); // Error: Argument of type '"B"' is not assignable to parameter of type '"C"'

此当前解决方案的错误是
接口“ValidationTextBox”错误地扩展了接口“TextBox”。
因为在
getObj(…)
中“B”不可分配给“C”


谢谢你的帮助

可能有几种解决方案。最简单的方法是通过指定额外的重载使编译器满意,但不使用类型查询重新编写它们:

interface ValidationTextBox extends TextBox {
    // The extra overload with C, and whatever overloads are in the base class (TextBox['getObj'])
    getObj: ((name: "C") => boolean) & TextBox['getObj'];
}
另一种解决方案是将类型设置为泛型,以允许我们添加到
name
参数的类型中,而不会实际覆盖该方法:

interface BaseWidget<TName = string> {
    getObj(name: TName): any
}


// TName can be used to add to the getName overload in derived interfaces
interface TextBox<TName = never> extends BaseWidget<TName | "B"> {
}

// TName can be used to add to the getName overload in derived interfaces
interface ValidationTextBox<TName = never> extends TextBox<TName | "C"> {
}

declare const obj: ValidationTextBox;
console.log(obj.getObj("B"));
console.log(obj.getObj("C"));
interface-BaseWidget{
getObj(名称:TName):任何
}
//TName可用于添加到派生接口中的getName重载中
接口文本框扩展BaseWidget{
}
//TName可用于添加到派生接口中的getName重载中
接口验证TextBox扩展了TextBox{
}
声明常量对象:ValidationTextBox;
console.log(obj.getObj(“B”));
console.log(obj.getObj(“C”));

在尝试了一段时间后,我发现了另一个几乎完美满足我需求的解决方案:

/--Properties接口设置getObj/setObj--//
接口属性{
getObj(名称:U):T[U]
setObj(名称:U,值:T[U]):void;
setObj(map:{[key in U]:T[key]}):void;
}
//---TextBox类使用的一些数据类接口--//
接口值{
a:数字;
}
接口MoreSomeValue扩展了SomeValue{
b:弦;
}
//---定义类的属性----//
接口TextBoxProps{
value:ValueType;//可以(必须?)通过泛型完全更改继承类中的属性类型
禁用:布尔值;
test:SomeValue;//但是重写以返回更具体的值是可以的
}
接口验证TextBoxProps扩展了TextBoxProps{
min:编号;
最大:数量;
测试:更多值
}
//---扩展属性的实际类接口---//
接口文本框扩展了_属性{}
接口验证TextBox扩展了_属性,TextBox{}
//---允许设置属性的构造函数--//
接口验证TextBoxConstructor{
//部分,因为所有属性都是可选的
新增(道具:部分):ValidationTextBox;
}
declare const ValidationTextBoxConstructor:ValidationTextBoxConstructor;//实际建造师
//---用法--//
//以下是编译时检查的所有类型,更改任何道具/字符串/值都将导致编译时错误
const obj=新的ValidationTextBoxConstructor({min:0,max:5,disabled:true});
日志(obj.getObj(“测试”));
对象设置对象(“最小”,5);
setObj({min:5,max:0,disabled:false});

解决方案的核心是_属性接口。在此基础上进行扩展并指定泛型类型T使您可以使用
getObj(name:string)
访问,其中name必须是所提供类型的键,并且它将返回类型T[name]。同样适用于
setObj(名称:string,值:T[U])
,其中值必须是由T[name]指定的类型。第二个
setObj
函数还接受{key=>value}的散列,并对提供的每个键调用setObj(key,value)。该类型还正确地检查传入的对象,方法是允许T的任何键,并使其值的类型为T[key]

*Props接口只定义可用的属性,并用作_属性中的类型。如果使用它们的类从另一个扩展_属性的类扩展,则它们应该相互扩展

这还提供了一个构造函数,可以选择获取属性名并设置它们


唯一的问题是,如果属性需要完全更改其类型(例如,基类具有string属性,但继承类将其公开为数字),但这可以通过Props接口上的泛型解决。这不是最干净的解决方案,但非常罕见,对我的需求来说没有太大影响。

难以置信!非常感谢。我不知道在接口中可以使用这样的类型查询。我会再多考虑一下,但我相信第一个选择就是我要寻找的。事实上,我在这些方法中遇到了一些问题。当多个类上有很多属性时,第一个方法会变得有点笨拙(最终在接口属性上有很多类型交集),而泛型方法只允许指定名称,但将返回类型保留为any。我在下面发布了我自己的答案,灵感来自于你在这里提到的通用方法。