![](/img/trans.png)
[英]Typescript: trying to use `extends` in generics with `this` in the interface
[英]Typescript interface generics extends
給定以下界面:
interface IMyInterface<T extends { [key: string]: number }> {
target: T;
to: T;
}
我想將其更改為
interface IMyInterface<T extends { [key: string]: number }> {
target: P extends T;
to: T;
}
目標可以是任何對象,只要它包含T中定義的屬性即可。
例:
let obj = <IMyInterface>{
target: { name:"John", age: 100 },
to: { age: 200 }
}
打字稿編譯器應在以下情況下抱怨:
let obj = <IMyInterface>{
target: { name:"John", y: 1980 },
to: { x: 20 }
}
“目標”中缺少“ x”屬性的位置
和
let obj = <IMyInterface>{
target: { name:"John", x: "20" },
to: { x: 30 }
}
類型錯誤的地方(數字與字符串)
即我要對目標進行類型檢查,以便它包含“ T”泛型中定義的所有屬性。
我希望將此作為一個對象。
創建類似的方法
methodName<T extends { [key: string]: number }>(target: T, to: T){
}
// and calling it
methodName({ name:"John", x: "20" },{x:30});
即使用“ target”和“ to”的單獨參數工作,並且Typescript中的類型檢查是完美的,但是我需要將“ target”和“ to”封裝在一個對象中,以便可以使用類似以下方法:
methodName<IMyInterface>(object: IMyInterface){
並這樣稱呼它:
methodName({ target: { name:"John", age:20 }, to: { age: 30}});
謝謝你的幫助
首先IMyInterface
的幾句話:首先,每當編寫IMyInterface
,都需要指定type參數。 就像是
let obj = <IMyInterface> { // error
target: { name:"John", age: 100 },
to: { age: 200 }
}
始終會出錯,因為您遺漏了type參數。 這將起作用:
let obj = <IMyInterface<{ age: number }>> {
target: { name:"John", age: 100 },
to: { age: 200 }
}
或者,更常見的是,對於TypeScript,您可以注釋變量的類型,而不是聲明值的類型:
let obj: IMyInterface<{ age: number }> = {
target: { name:"John", age: 100 },
to: { age: 200 }
}
如果您的IMyInterface
定義指定了默認類型參數 ,則IMyInterface
類型參數 ,但這將無法按您希望的方式工作,因為默認值始終是相同的,並且您希望根據類型更改某些內容to
屬性。
我的下一個問題是:您是否希望P
僅用於檢查是否正確創建了IMyInterface<T>
? 因此,一旦創建了有效的IMyInterface<T>
您就可以立即忘記使用P
嗎? 看起來像它。 在那種情況下,我要做的是將P
排除在IMyInterface<T>
的定義之外,而使用輔助方法。 您注意到一種方法可以幫助您鍵入檢查,但您需要一個對象,對嗎? 好了,helper方法可以返回一個有效的IMyInterface<T>
:
namespace HelperFunctionSolution {
// original definition
interface IMyInterface<T extends { [key: string]: number }> {
target: T;
to: T;
}
// helper method
function makeMyInterface<T extends { [key: string]: number }, P extends T>(
target: P,
to: T
): IMyInterface<T> {
return { target, to };
}
現在,您可以使用輔助方法:
const goodObj = makeMyInterface({ name: "John", age: 100 }, { age: 200 }) // okay
如果檢查goodObj
您將看到它是goodObj
IMyInterface<{age: number}>
。 編譯器抱怨您想要在哪里:
const badObj0 = makeMyInterface({}, { x: 30 }) // x is missing
const badObj1 = makeMyInterface({ name: "John", y: 1980 }, { x: 30 })
// complains about extra property but real problem is x
const badObj2 = makeMyInterface({ x: "20" }, { x: 30 }) // complains about string
const badObj3 = makeMyInterface({ name: "John", x: "20" }, { x: 30 })
// complains about extra property but real problem is x
現在,您可以創建所需的方法:
class Hmm {
methodName<T extends { [key: string]: number }>(target: T, to: T) { /*impl*/ }
等等,那是您的定義,但我認為您希望它采用這樣的對象:
realMethodName<T extends { [key: string]: number }>(
myInterface: IMyInterface<T>
) { /*impl*/ }
}
並使用它, 確保使用helper函數 :
const hmm = new Hmm();
hmm.realMethodName(makeMyInterface({ name: "John", age: 20 }, { age: 30 })); // okay
}
您不能在其中使用對象文字並保證類型檢查,因為只有助手函數在乎P
因此,這是一種方法,但是您需要使用輔助函數。
另一種可能是您在IMyInterface
定義中隨身攜帶了P
類型。 這可能不是您想要的,但是它具有令人滿意的效果,您可以在methodName
方法中使用字符串文字,並且不需要幫助函數:
namespace TwoTypeParameterSolution {
interface IMyInterface<T extends { [key: string]: number }, P extends T> {
target: P;
to: T;
}
class Hmm {
realMethodName<T extends { [key: string]: number }, P extends T>(
myInterface: IMyInterface<T,P>
) { /*impl*/ }
}
const hmm = new Hmm();
hmm.realMethodName({target: { name: "John", age: 100 }, to: { age: 200 }}) // okay
hmm.realMethodName({target: {}, to: { x: 30 }}) // x is missing
hmm.realMethodName({target: { name: "John", y: 1980 }, to: { x: 30 }})
// complains about extra property but real problem is x
hmm.realMethodName({target: { x: "20" }, to: { x: 30 }}) // complains about string
hmm.realMethodName({target: { name: "John", x: "20" }, to: { x: 30 }})
// complains about extra property but real problem is x
hmm.realMethodName({ target: { name: "John", age: 20 }, to: { age: 30 } }); // okay
}
兩種方法都應該為您工作。 希望能有所幫助; 祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.