[英]Type that depends on generic argument as value argument to function
我有一個看起來像這樣的通用類型Group
:
// K -> Key
// I -> Input
type Group<K, I> = {
key: K;
func: (i: I) => void;
};
我在 object 中聲明了固定數量的Group
值,如下所示:
const GROUPS = {
"a": {
func: (i: {x: number}) => { console.log(i); },
key: "a",
},
"b": {
func: (i: { y: number }) => { console.log(i) },
key: "b"
}
} as const;
然后,我有 2 種實用程序類型來引用所有可能的組鍵和所有可能的組輸入:
type GroupKey = keyof typeof GROUPS;
type GroupInput<K extends GroupKey> = Parameters<typeof GROUPS[K]["func"]>[0];
// GroupValue test:
type TestType = GroupInput<"b">; // { y: number}, this works
最后,我有一個 function 接收組鍵和組輸入:
function test<K extends GroupKey>(key: K, input: GroupInput<K>) {
if (key === "b") {
(input.y); // Why doesn't TypeScript understand that `input.y` must be `number` here?
}
}
這個 function 對於傳入的鍵的類型是通用的,不幸的是,TypeScript 無法“理解”如果key
是"b"
,那么input
的類型是{ y: number }
。 為什么會出現這種情況,TypeScript 缺少什么才能做到這一點? 我特別想在這個問題上找到一個 GitHub 問題(以便我可以訂閱它),但我無法找到一個,因為這種類型的東西特別難以搜索。
請考慮這個片段:
const key = 'a' as GroupKey
const input = { y: 1 } // optionally cast as GroupInput<'b'> or as GroupInput<GroupKey>
test(key, input) // compiles, but not intended
input
可能獨立於key
。 不能保證input.y
必須是一個數字,當test
被調用時,值'b'
作為第一個參數。 type TestType = GroupInput<"b">
使用文字類型( 'b'
),它允許 Typescript 限制'a' | 'b'
'a' | 'b'
到'b'
。 這同樣適用於test('b', ...)
,但傳遞類型為'a' | 'b'
'a' | 'b'
允許傳遞GroupInput<'a' | 'b'>
類型的輸入 GroupInput<'a' | 'b'>
。
一種選擇是檢查'y' in input
,但這仍然不能解決不允許錯誤的 arguments 進行test
的主要問題。 通常情況下input as GroupInput<'b'>
是不安全的,應不惜一切代價避免。
一個可能的修復:
type Params = { [K in GroupKey]: [key: K, input: GroupInput<K>] } // key: and input: are used for auto-completion instead of generic arg_0, arg_1
function test2(...args: Params[GroupKey]) {
// const [key, input] = args // will not work
if (args[0] === "b") {
const input = args[1];
input.y; // number
}
}
test2('b', { y: 1 }) // ok
test2('b', { x: 1 }) // error
test2(key, input) // error
因為input
參數獨立於您的key
參數。 盡管您的鍵可能等於'b'
,但input
不需要將y
作為屬性。 您必須對您的input
進行類型轉換:
function test<K extends GroupKey>(key: K, input: GroupInput<K>) {
if (key === "b") {
const typedInput = input as GroupInput<'b'>;
(typedInput.y)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.