使用函数注释时出现打字稿错误'keyof extends'



对于TS类型系统的各个方面来说仍然是新的。我收到一个'?' expected [1005]错误。

使用TS 3.1.6版

我的tsconfig编译器选项:

"compilerOptions": {
"strict": true,
"module": "commonjs",
"outDir": "www/staging/js",
"rootDir": "src/",
"sourceMap": false,
"target": "es5",
"experimentalDecorators": true
},

导致该问题的代码是handler参数类型注释(特别是在_convert方法的右括号之前的位置(:

private _convert(
doc: any, 
handler: keyof StringHelperService extends (str: string) => string
): any {
let converted = {} as {[str: string]: any}
for (let prop in doc) {
converted[handler(prop)] = doc[prop];
}
return converted;
}

注释应该说"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);
}
}

我已经解决了这个问题

以下是_convert的实现者,以帮助解释该方法是如何使用的,以及它与StringHelperService的关系。我为函数声明创建了一个接口:

export interface StringConverter {
(str: string): string;
}

通过使用这个接口代替helper的原始注释,我解决了这个问题。问题是我最初的注释完全错误。我的谬论源于误解,即我会使用key of类型来注释类型T的成员的类型,而实际上这是我想要的METHOD。不知道我为什么要这么跳。

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);
}
}

注释应该说"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>;

不过,您给出的示例是一个不同的用例。在本例中,handler不是string,而是具有特定签名的函数。

pascalToCamel(doc: any): any {
// the second argument is a function not a string
return this._convert(doc, this.stringHelper.pascalToCamel);
}

在这种情况下,您似乎真正想要的_convert是:

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

最新更新