Typescript 使用'时出现键入脚本错误;keyof extends';功能注释

Typescript 使用'时出现键入脚本错误;keyof extends';功能注释,typescript,Typescript,对TS类型系统的各个方面仍然是新的。我收到一个“”?”预期为[1005]错误 使用TS版本3.1.6 My Tconfig编译器选项: "compilerOptions": { "strict": true, "module": "commonjs", "outDir": "www/staging/js", "rootDir": "src/", "sourceMap": false, "target": "es5", "experiment

对TS类型系统的各个方面仍然是新的。我收到一个“
”?”预期为[1005]
错误

使用TS版本3.1.6

My Tconfig编译器选项:

"compilerOptions": {
    "strict": true,
    "module": "commonjs",
    "outDir": "www/staging/js",
    "rootDir": "src/",
    "sourceMap": false,
    "target": "es5",
    "experimentalDecorators": true
  },
导致问题的代码是
处理程序
参数类型注释(特别是在
\u convert
方法的右括号之前的位置):

注释应该是“StringHelperService的密钥,仅当它具有以下函数签名时”。以下是StringHelperService:

export class StringHelperService {
  public static $inject: ReadonlyArray<string> = [];


  constructor() {
    this.pascalToCamel = this.pascalToCamel.bind(this);
    this.camelToPascal = this.camelToPascal.bind(this);
  }


  pascalToCamel(str: string): string {
    return str.substring(0, 1).toLowerCase() + str.substring(1);
  }


  camelToPascal(str: string): string {
    return str.substring(0, 1).toUpperCase() + str.substring(1);
  }
}
通过使用此接口代替
helper
的原始注释,我解决了这个问题。问题是我最初的注释完全错误。我的谬误源于一种误解,即我会使用类型为的
键来注释类型为T的成员的类型,而实际上这是我想要的方法。我不知道我为什么要这样做

export class PropertyNameConverterService {
  public static $inject: ReadonlyArray<string> = ['stringHelper'];


  constructor(private stringHelper: StringHelperService) {
    this._convert = this._convert.bind(this);
    this.pascalToCamel = this.pascalToCamel.bind(this);
    this.camelToPascal = this.camelToPascal.bind(this);
  }


  private _convert(
    doc: any, 
    handler: StringConverter
  ): any {
    let converted = {} as {[str: string]: any}

    for (let prop in doc) {
      converted[handler(prop)] = doc[prop];
    }
    return converted;
  }


  pascalToCamel(doc: any): any {
    return this._convert(doc, this.stringHelper.pascalToCamel);
  }


  camelToPascal(doc: any): any {
    return this._convert(doc, this.stringHelper.camelToPascal);
  }
}
导出类PropertyNameConverterService{
公共静态$inject:ReadonlyArray=['stringHelper'];
构造函数(私有stringHelper:StringHelperService){
this.\u convert=this.\u convert.bind(this);
this.pascalToCamel=this.pascalToCamel.bind(this);
this.camelToPascal=this.camelToPascal.bind(this);
}
专用转换(
医生:有吗,
处理程序:StringConverter
):任何{
让转换={}为{[str:string]:any}
for(让道具进入文档){
转换后的[经办人(道具)]=单据[道具];
}
转换收益;
}
帕斯卡托卡迈尔(医生:任何):任何{
返回此.\u convert(doc,this.stringHelper.pascalToCamel);
}
Camletopascal(医生:任何):任何{
返回此.\u convert(doc,this.stringHelper.camelToPascal);
}
}
注释应该是“StringHelperService的密钥,仅当它具有以下函数签名时”

这就是您希望注释执行的操作

type KeysWithThisSignature<T, U> = {
    [P in keyof T]: T[P] extends U ? P : never;
}[keyof T]

// type Keys = "pascalToCamel" | "camelToPascal"
type Keys = KeysWithThisSignature<StringHelperService, (str: string) => string>;
在这种情况下,您对
\u convert
真正想要的是:

private _convert(doc: any, handler: (str: string) => string): any {
    // ...
}

请举例说明如何使用
\u convert
方法。是的。我把整个班级都加到了作品中。啊,这帮我找到了问题所在。我会更新帖子的。感谢您希望
处理程序
是一个键,但您将其视为方法中的一个函数。不知道你在做什么。如果你真的需要钥匙,请告诉我们;正如参数名所暗示的那样,我需要一个函数。我感到困惑,并假设使用了关键注释。我已经用正确的类型注释更新了这篇文章。我找到了一个带有接口的解决方案,但是还不能完全确定它为什么会起作用。这个答案很好地解释了这一点。谢谢
type KeysWithThisSignature<T, U> = {
    [P in keyof T]: T[P] extends U ? P : never;
}[keyof T]

// type Keys = "pascalToCamel" | "camelToPascal"
type Keys = KeysWithThisSignature<StringHelperService, (str: string) => string>;
pascalToCamel(doc: any): any {
    // the second argument is a function not a string
    return this._convert(doc, this.stringHelper.pascalToCamel);
}
private _convert(doc: any, handler: (str: string) => string): any {
    // ...
}