下面是我想要做的一些代码:

  1. 具有几个成员字段和函数的类;
  2. 这个类提供一个名为callMe的函数;
  3. callMe的参数将被限制为此类的成员名称之一;
  4. 只接受成员字段的名称,应排除成员函数的名称.

奇怪的是:

  1. 如果我用一个实例调用callMe函数,一切都会像预期的那样顺利.
  2. 但是,如果我在这个类的成员函数中调用callMe,就会出现错误.

详情如下:

// I'd like to use this `Filter` to get all the non-function field names of a type
type Filter<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] & string;

class BaseClass {
  // This function should only accept a parameter which only matches the non-function member names
  public callMe<V extends Filter<this>>(param: V) {}
}

class MyClass extends BaseClass {
  // These member field should be involved
  public stringField: string = '';
  public numberField: number = 0;
  public booleanField: boolean = false;
  // These member functions should be excluded
  public shouldBeExclude() {}
  public test() {
    // this line is error:
    // TS2345: Argument of type string is not assignable to parameter of type Filter<this>
    // Type 'string' is not assignable to type 'this[keyof this] extends Function ? never : keyof this'
    this.callMe('stringField');
  }
}

const instance = new MyClass();
// However these lines work as expected
instance.callMe('stringField'); // Valid
instance.callMe('numberField'); // Valid
instance.callMe('shouldBeExclude'); // Invalid: TS2345: Argument of type 'shouldBeExclude' is not assignable to parameter of type Filter<MyClass>


Playground

我怎样才能使Filter与成员函数test一起工作?

推荐答案

TypeScrip本身并不能真正解决这个问题,相反,我建议您通过泛型将显式类型传递给父类.这样,您将自动一次在所有方法中进行正确的类型判断:

// I'd like to use this `Filter` to get all the non-function field names of a type
type Filter<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T] & string;

class BaseClass<Child> { // here we add a generic type
  public callMe<V extends Filter<Child>>(param: V) { }
}

class MyClass extends BaseClass<MyClass> {
  // These member field should be involved
  public stringField: string = '';
  public numberField: number = 0;
  public booleanField: boolean = false;
  // These member functions should be excluded
  public shouldBeExclude() { }
  public test() {
    this.callMe('stringField');  // Is valid now
  }
}

const instance = new MyClass();
instance.callMe('stringField'); // Valid
instance.callMe('numberField'); // Valid
instance.callMe('shouldBeExclude'); // Invalid: TS2345: Argument of type 'shouldBeExclude' is not assignable to parameter of type Filter<MyClass>

TS Playground

Typescript相关问答推荐

如何将单元测试中的私有订阅变量设置为空(或未定义)?

我用相同的Redux—Toolkit查询同时呈现两个不同的组件,但使用不同的参数

将对象属性转换为InstanceType或原样的强类型方法

如何设置绝对路径和相对路径的类型?

Angular 信号:当输入信号改变值时,S触发取数的正确方式是什么?

如何判断对象是否有重叠的叶子并产生有用的错误消息

缩小并集子键后重新构造类型

通过按键数组拾取对象的关键点

在Reaction-Native-ReAnimated中不存在Animated.Value

以Angular 自定义快捷菜单

TypeError:正文不可用-NextJS服务器操作POST

如何从输入中删除值0

如何正确调用创建的类型?

为什么上下文类型在`fn|curred(Fn)`的联合中不起作用?

如何通过转换器类继承使用多态将对象从一种类型转换为另一种类型

对于VUE3,错误XX不存在于从不存在的类型上意味着什么?

如何在Next.js和Tailwind.css中更改悬停时的字体 colored颜色

参数未映射泛型返回类型

通过函数传递确切的类型,但验证额外的字段

React Context TypeScript错误:属性';firstName';在类型';iCards|iSearch';