对于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的成员的类型,而实际上的确是我想要的方法。不知道为什么我会飞跃。
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);
}
}
答案 0 :(得分:2)
该批注应该是“ 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 {
// ...
}