这是某些函数的实际(简化)示例
lab
const lab = <
T extends Something,
K extends keyof T
>(k: T[K] extends (...args: any[]) => any ? K : never) => {
return ({} as T)[k];
}
const test = lab<Something, 'fn'>('fn')
type Something = {
str: string,
num: number
bool: boolean,
fn: (a: number, b: number) => number,
}
它按预期工作。但通过下面的屏幕,我展示了我也想要的东西,但不明白为什么这是不可能的。
允许通用占位符中的
str
作为Something
的键,但参数错误...所以又名工作如果参数变成
str
也会发生错误...所以又名工作允许
fn
并在争论中提示它......很好!
fn
?或者至少任意一个 Something
键又名 str
、num
...?您正在寻找 IntelliSense,以便在调用 K
函数时为类型参数 lab()
的 generic
类型参数自动建议完成列表。但 TypeScript 的 IntelliSense 支持不提供此类补全。您可以用一个最小的示例来展示这一点,例如:
const f = <K extends "x" | "y">() => 0;
f<"x">() // okay
f<"">()
// ^ abc "A"
// ^ abc "a"
// ^ abc "All"
// ^ abc "all"
// ...
在这里,IntelliSense 推荐
"x"
或 "y"
应该非常容易,但是您会得到 TypeScript 知道的所有字符串文字的完整列表。
microsoft/TypeScript#28662 有一个长期开放的功能请求要求这样做。如果你想看到它发生,你可能想去那里给它一个👍。但除非它被实施,否则你需要放弃或解决它。
如果您愿意使用 values 而不是 types 那么您可以 curry 您的函数,以便您手动指定
T
的类型参数,然后返回的函数会将 K
限制为您想要的类型想支持,那就不用手动指定K
;相反,您只需使用 K
类型的值调用该函数,即可获得函数参数的 IntelliSense 完成列表:
const lab = <T extends Something>() =>
<K extends { [P in keyof T]:
T[P] extends (...args: any) => any ? P : never
}[keyof T]>(
k: K
) => { return ({} as T)[k]; }
const test = lab<Something>()("") // <--
// ^🔧 fn
在这里您指定了
Something
,然后您得到 fn
作为返回函数的建议输入。
仅当您确实需要
K
具有通用性时才需要柯里化;你可能不会:
const lab = <T extends Something>(k: { [P in keyof T]:
T[P] extends (...args: any) => any ? P : never
}[keyof T]) => { return ({} as T)[k]; }
const test = lab<Something>("") // <--
// ^🔧 fn
但这有点偏离问题的答案,即:如果没有 microsoft/TypeScript#28662,您想要的完成列表是不可能的。