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

标签 typescript

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

BaseWidget --> TextBox --> ValidationTextBox

BaseWidget 提供了一个名为getObj(name) 的JS 函数映射到 getObj(name: string): any在 TS 中并有效地在当前对象上查找名为 _get<name> 的函数, 执行它,并返回结果。

这些“属性”在各个类上公开,并在类之间继承,这样 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"'

TS Playground link

当前解决方案的错误是 Interface 'ValidationTextBox' incorrectly extends interface '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"));

关于Typescript 继承并重载了函数的字符串文字参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51017009/

相关文章:

angular - TS2339 : Property 'text' does not exist on type '{}'

reactjs - React.SFC 给出 Element vs ReactElement<any> 错误,ValidationMap

angular - 密码验证在 Angular 5 中不起作用

javascript - 使用 VS Code、TypeScript 和 Node.js 的断点位置不正确

angular - 使用已知/声明的组件插入动态 Angular 4.x 内容

typescript - 将数据传递给根 Vue 类组件

typescript - infer 关键字从基类获取泛型类型

javascript - 按父实体和虚线路径列出的实体列表

javascript - ServiceWorker 的 TypeScript 类型定义

typescript - 在 TypeScript 中调用以联合作为其返回类型的函数后,如何获得 vscode 自动完成功能?