typescript - 在这些情况下“K 不能用于索引类型”的原因
问题描述
TypeScript 版本:4.1.5(严格模式)
我的问题
我在这里似乎缺少 TypeScript 类型系统的一个元素。
我不确定为什么在以下情况下会出现相应的 TypeScript 错误。我怀疑它们之间存在某种等价关系。
请注意,在 getOption 1、2 和 3 中,TypeScript 如何产生错误。但是,在 getOption 4 和 5 中,没有这样的错误。请任何人帮助我理解为什么在这种情况下,1-3 有错误,但 4-5 没有。
用例
我希望 A 的派生类包含扩展的 Options 属性,使用扩展的 Options 接口。而且我希望基类中的方法始终推断与调用上下文中的当前实例关联的类型。
示范
interface Options {
test: boolean;
}
class A {
private options: Options;
constructor(options: Options) {
this.options = options;
}
// Setting the 'this' arg doesn't change anything
getOptions(this: A): Options {
return this.options;
}
// Doesn't work - TS2536: Type 'K' cannot be used to index type 'Options'.
getOption1<O extends Options, K extends keyof O>(name: K): O[K] {
const options = this.getOptions();
return options[name];
}
// Doesn't work - TS2536: Type 'keyof ReturnType' cannot be used to index type 'Options'.
getOption2(name: keyof ReturnType<this['getOptions']>): ReturnType<this['getOptions']>[keyof ReturnType<this['getOptions']>] {
const options = this.getOptions();
return options[name];
}
// Doesn't work - two of the same error:
// TS2536: Type 'keyof ReturnType' cannot be used to index type 'Options'.
getOption3(name: keyof ReturnType<this['getOptions']>): Options[typeof name] {
const options = this.getOptions();
// TS2536: Type 'keyof ReturnType ' cannot be used to index type 'Options'.
return options[name];
}
// Works
getOption4(name: keyof Options): Options[typeof name] {
const options = this.getOptions();
return options[name];
}
// Works
getOption5(name: keyof Options): ReturnType<this['getOptions']>[typeof name] {
const options = this.getOptions();
return options[name];
}
}
谢谢你。
解决方案
问题是选项也可以是子类型,因此与其他选项类型不匹配。
这有效:
interface Options {
test: boolean;
}
class A {
private options: Options;
constructor(options: Options) {
this.options = options;
}
// Setting the 'this' arg doesn't change anything
getOptions(this: A): Options {
return this.options;
}
getOption1<O extends Options, K extends keyof O>(name: K): O[K] {
const options = this.getOptions() as O;
return options[name];
}
getOption2(name: keyof ReturnType<this['getOptions']>): ReturnType<this['getOptions']>[keyof ReturnType<this['getOptions']>] {
const options = this.getOptions() as ReturnType<this['getOptions'];
return options[name];
}
getOption3(name: keyof ReturnType<this['getOptions']>): ReturnType<this['getOptions']>[typeof name] {
const options = this.getOptions() as ReturnType<this['getOptions']>;
// TS2536: Type 'keyof ReturnType ' cannot be used to index type 'Options'.
return options[name];
}
// Works
getOption4(name: keyof Options): Options[typeof name] {
const options = this.getOptions();
return options[name];
}
// Works
getOption5(name: keyof Options): ReturnType<this['getOptions']>[typeof name] {
const options = this.getOptions();
return options[name];
}
}
但在这种特定情况下,您可能希望为选项创建一个通用类参数:
class A<TOptions extends Options> {
private options: TOptions;
constructor(options: TOptions) {
this.options = options;
}
getOptions(): TOptions {
return this.options;
}
getOption<K extends keyof TOptions>(name: K): TOptions[K] {
const options = this.getOptions();
return options[name];
}
}
推荐阅读
- sql - SQL OPENQUERY,'+' 附近的语法不正确
- django - “HSH.Usuario.email: (models.E006) 'email' 字段与模型 'HSH.usuario' 中的 'email' 字段冲突”
- php - php代码有问题,运行,但不会执行
- node.js - React 应用程序在 Internet Explorer 11 中不起作用
- spring - Hibernate 和 JPA @PreUpdate 和 @PrePersist 不起作用
- php - PHP 警告:count():参数必须是数组还是实现 Countable 的对象?
- variables - SSIS 使用 OLEDB 源的表名填充变量
- javascript - 如何使用 React ChartJs 只为每个第 n 个数据点显示一个点?
- reactjs - 发送查询 Apollo 客户端时出现网络错误
- java - 在循环内部/外部使用“Runtime.getRuntime()”