假設我們有以下物件:
interface X {
a: () => number;
b: number;
}
以及以下型別:
type MethodsOf<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T];
該MethodsOf
型別只會縮小其值為函式的物件的鍵。例如:
type A = MethodsOf<X>; // "a"
const a: A = 'a';
const b: A = 'b'; // Error: Type '"b"' is not assignable to type '"a"'.
現在我正在嘗試創建一個泛型型別,它將接收一個X
介面,但將回傳一個其鍵被縮小到MethodsOf<X>
的型別,其值是MethodsOf<X>
. 例子:
type ValuesMapping<T> = ???
// No error:
const mapping: ValuesMapping<X> = {
a: 3
}
// Error:
const mapping: ValuesMapping<X> = {
a: 'blarg'
}
我試圖實作type ValuesMapping<T>
如下:
type ValuesMapping<T> = {
[K in MethodsOf<T>]: ReturnType<T[K}>;
};
但我收到以下錯誤:
TS2344: Type 'T[K]' does not satisfy the constraint '(...args: any) => any'. Type 'T[MethodsOf<T>]' is not assignable to type '(...args: any) => any'. Type 'T[T[keyof T] extends (...args: any[]) => any ? keyof T : never]' is not assignable to type '(...args: any) => any'. Type 'T[keyof T]' is not assignable to type '(...args: any) => any'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type '(...args: any) => any'. Type 'T[string]' is not assignable to type '(...args: any) => any'.
對于該問題的某些背景關系,我正在嘗試創建一個通用的模擬型別:
type MethodsOf<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T];
type MockMapping<T> = {
[K in MethodsOf<T>]: Mock<ReturnType<T[K]>>;
};
// usage
class X {
a() {
return 1;
}
b = 2;
}
const x: MockMapping<X> = {
a: jest.fn(() => 42),
};
任何幫助,將不勝感激!
uj5u.com熱心網友回復:
TypeScript 無法理解計算K
的鍵只指向有效的函式屬性。TypeScript 唯一確定的是它實際上是. 這就是為什么索引仍然是可能的。T
MethodsOf<T>
K
T
所以我們需要通過使用另一個條件來幫助 TypeScript 理解T[K]
應該是什么。
type ValuesMapping<T> = {
[K in MethodsOf<T>]:
ReturnType<T[K] extends (...args: any[]) => any ? T[K] : never>;
};
這編譯沒有錯誤。
操場
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/527576.html
標籤:打字稿仿制药打字稿打字
上一篇:在TypeScript中訪問錯誤屬性的慣用方法是什么?
下一篇:如何從物件聯合中獲取物件值型別