打字稿“keyof InstanceType<T>”不能用于索引类型错误

时间:2021-06-15 03:34:35

标签: javascript typescript

示例代码如下:

class Base {}

function fn<T extends typeof Base>(
    Cls: T,
    prop: keyof InstanceType<T>,
) {
    return (new Cls())[prop];
}

TS 游乐场:https://www.typescriptlang.org/play?#code/MYGwhgzhAEBCkFNoG8C+AodAzArgO2ABcBLAez2izwB4AVaBAD0ITwBMZCBPABwVKxxEAPgAU6aJOgBhEBABc0WgBoJUngCdSPRQGsEXAdACSeCITAEEtXgjrDVAShRrJGhIRwaKovAgDuMnKijo4A2praALoA3OgYQA

prop 应该是 Cls 上的一个属性,但此代码不起作用?

如果我将 keyof InstanceType<T> 更改为 keyof Base,它会起作用,但我希望该函数可以与 Base 的任何子类一起使用。

4 个答案:

答案 0 :(得分:2)

InstanceType 用于泛型时,TypeScript 编译器的反应似乎很糟糕。

如果将泛型参数更改为实例类型,它就可以工作,这应该等同于原始代码:

function fn<T extends Base>(
    Cls: new () => T, 
    prop: keyof T
) {
    return new Cls()[prop];
}

答案 1 :(得分:1)

这是可行的:

class Base {
  base = 'base'
}

class A extends Base {
  a = 'a'
}
class B extends Base {
  b = 'b'
}

class C {
  c = 'c'
}


const fn = <
  T extends typeof Base,
  Instance extends InstanceType<T>
>(Cls: new () => Instance, prop: keyof Instance,
) => new Cls()[prop];

const result = fn(A, 'base') // ok

const result2 = fn(B, 'b') // ok

const result3 = fn(Base, 'base') // ok

const result4 = fn(A, 'b') // expected error

const result5 = fn(B, 'a') // expected error

const result6 = fn(C, 'x') // expected error

答案 2 :(得分:0)

这里有几个问题:

class Base {}

function fn<T extends typeof Base>(
    Cls: T, // <--- Cls is already an instance of T
    prop: InstanceType<T>, // <-- if you want properties of the class use keyof T
) {
    return (new Cls())[prop]; // <-- You cannot call new on instance
}

考虑到这些,这可能对您有用:

class Base {}

function fn<T extends Base>(
    Cls: T,
    prop: keyof T,
) {
    return Cls[prop];
}

TS 游乐场:https://tsplay.dev/WJ9DDm

但是,如果您将类传递给 fn 而不是实例,那么 Wang Weixuan 的答案更适合。

答案 3 :(得分:0)

没有必要new ClsInstanceType试试这个:

class Base {}

function fn<T extends typeof Base>(Cls: T,prop: keyof T) {
     return Cls[prop];
}