我們想在超類上創(chuàng)建一個(gè)泛型方法,該方法接受一個(gè)參數(shù),該參數(shù)是子類上某一類型的任何屬性的名稱。考慮一下這個(gè)(非常做作的)例子:
class CanUpcase {
upcase<PropertyName extends keyof this>(
propertyName: this[PropertyName] extends string ? PropertyName : never
) {
return this[propertyName].toUpperCase(); // Property 'toUpperCase' does not exist on type 'this[this[PropertyName] extends string ? PropertyName : never]'.
}
}
class User extends CanUpcase {
age = NaN;
name = ``;
constructor() {
super();
this.upcase('name'); // Argument of type '"name"' is not assignable to parameter of type 'this["name"] extends string ? "name" : never'.ts(2345)
}
}
const user = new User();
user.upcase('name'); // No error
我們預(yù)期upcase
會(huì)接受'name'
,因?yàn)?code>'name'屬性是一個(gè)字符串。
然而,當(dāng)user.upcase('name')
按預(yù)期工作時(shí),this.upcase('name')
拋出了一個(gè)錯(cuò)誤,如圖所示。
此外,在upcase
內(nèi),this[propertyName]
不被識(shí)別為字符串。
- 為什么
this.upcase
拋出錯(cuò)誤而不是user.upcase
? - 為什么
this[propertyName]
不被識(shí)別為字符串?
Thanks!
關(guān)鍵問(wèn)題在于這條線:
盡管我們將propertyName限制為僅包含[propertyName]為字符串的鍵,但TypeScript不會(huì)將此約束應(yīng)用于此[propertyName]的解析類型。這是由于使用條件類型時(shí)TypeScript的類型推理限制造成的。
解決方案:使用顯式泛型約束