![](/img/trans.png)
[英]Is it possible to infer return type of functions in mapped types in typescript?
[英]TypeScript: Infer specific types of arguments and return values of functions in a mapped object
我正在嘗試為我的模塊構建一個類型保護的接口。
一個簡化的版本是這樣的:
const userResult = myFunc({
foo: (key, arg) => {
// users do something here with:
// - key inferred as "foo" and
// - arg inferred as string
return "foobar";
},
bar: (key, arg) => {
// users do something here with:
// - key inferred as "bar" and
// - arg inferred as number
return 1;
},
})
這里myFunc
是我的模塊的接口函數。 用戶可以傳遞帶有任意鍵的對象(示例中的foo
和bar
)和特定類型的函數,其參數是key
和arg
,返回值是字符串(示例中的"foobar"
)或數字(示例中的1
例子)。
我的目標是將arg
的類型推斷為與函數的返回值相同的類型,同時將鍵的類型設置為與條目的key
相同的字符串文字。
我已經為此苦苦掙扎了很長時間,但我設法發現它幾乎完美地工作:
type Value = string | number;
type MyType<K, T extends Value> = (key: K, arg: T) => T;
function myFunc<
Ks extends keyof R,
R extends { [K in Ks]: MyType<K, Value> },
>(
userObj: {
[K in Ks]: R[K];
},
) {
// do some complicated staffs
}
TypeScript 對示例用戶輸入的類型推斷結果為:
function myFunc<"foo" | "boo", {
foo: (key: "foo", arg: Value) => string;
boo: (key: "boo", arg: Value) => number;
}>(userObj: {
foo: (key: "foo", arg: Value) => string;
boo: (key: "boo", arg: Value) => number;
}): ResultType // whatever type we return
最后一個缺失點是arg
被推斷為值,而不是特定類型(字符串為foo
和數字為boo
。)
有什么解決辦法嗎? 任何提示或評論將不勝感激。
假設每個鍵的 arg 類型應該始終相同,定義映射類型可能很有用,然后從中派生您的類型。 在這種情況下, ParamValues
是一個對象類型,我們將使用每個屬性的類型來對應函數 arg 的類型和返回值:
function myFunc<ParamValues>(userObj: {
[K in keyof ParamValues]: (key: K, arg: ParamValues[K]) => ParamValues[K];
}) {
// do something here
}
// Explicitly define the arg types per key
type SpecificValues = {
foo: string,
bar: number
}
myFunc<SpecificValues>({
foo: (key, arg) => "Wa",
bar: (key, arg) => arg + 1
})
// These fail because the operations being done on arg are not
// supported by the value types from `SpecificValues`
myFunc<SpecificValues>({
// @ts-expect-error
foo: (key, arg) => arg * 3,
// @ts-expect-error
bar: (key, arg) => arg.slice(3),
// @ts-expect-error
baz: (key, arg) => arg + arg;
})
或者你可以使用類型推斷,但在某些時候你必須告訴編譯器你的類型是什么:
// This implies myFunc<{ blah: number, blag: string }>
myFunc({
blah: (key, arg: number) => 4,
blag: (key, arg: string) => "Woohoo!"
})
// This fails because return values do not match the arg types
myFunc({
// @ts-expect-error
blah: (key, arg: number) => "Yarg",
// @ts-expect-error
blag: (key, arg: string) => 3
})
簡而言之,我們的ParamValues
類型不是任何變量實際擁有的類型; 它只是一種定義鍵到類型的映射的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.