[英]Using "extends" on inferred mapped types in Typescript Generics
這是我的代碼和相關的游樂場:
type SomeType<T> = {
[K in keyof T]?: K extends 'u'
? string
: T[K] extends object
? SomeType<T[K]>
: object
}
function someType<T>(t: SomeType<T>) {
return t;
}
type BLA = SomeType<{
u: 1,
b: {
u: 1,
},
}>;
const blaBLA: BLA = {
u: 1, // <-- correct error msg: Type 'number' is not assignable to type 'string'.
b: {
u: 1, // <-- correct error msg: Type 'number' is not assignable to type 'string'.
},
};
const bla = someType({
u: 1, // <-- correct error msg: Type 'number' is not assignable to type 'string'.
b: {
u: 1, // <-- expected: error message from above
// the problem here is that the value for b was resolved to 'object' instead of 'SomeType<T[K]>'
// how can I fix this?
},
});
我正在尋找解決我在上面代碼中描述的問題的方法,或者解釋為什么它不能按照我認為的方式工作。
因為這純粹是為了學習(理解)TS,所以我對任何一種結果都可以。
如果您有類似的功能
function someType<T>(t: SomeType<T>) {
return t;
}
並用someType(val)
調用它,然后編譯器將嘗試推斷泛型類型參數T
假設val
是SomeType<T>
類型。 您要求編譯器從本質上反轉類型函數SomeType<T>
。
但這對於編譯器來說是不可能的,尤其是因為SomeType<T>
可能與SomeType<U>
相同,即使T
和U
不同:
type Hmm = SomeType<{ u: 1, b: "", c: { d: "" } }>;
/* type Hmm = {
u?: string;
b?: object;
c?: {d?: object}
} */
type Ugh = SomeType<{ u: true, b: 123, c: { d: false } }>;
/* type Ugh = {
u?: string;
b?: object;
c?: {d?: object}
} */
反轉類型函數並不總是可能的,或者即使可能,編譯器也不總是可行的。
幸運的是,這並不是您真正想要的行為。
相反,您似乎希望SomeType<T>
充當T
本身的遞歸約束。 我的意思是,當您調用someType(val)
時,您希望T
被推斷為val
的類型,然后您希望編譯器檢查T
是否也可分配給SomeType<T>
。
所以讓我們直接把它寫成一個通用的約束:
function someType<T extends SomeType<T>>(t: T) {
return t;
}
編譯沒有錯誤,所以我們可以繼續測試它:
const bla = someType({
u: 1, // error!
b: {
u: 1, // error!
},
});
看起來不錯。 你得到的正是你期望得到的錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.