typescript - 如何根据输入参数中的键推断数据?
问题描述
不太清楚为什么这不起作用。
type someTypes = "a" | "b" | "c"
type otherTypes = "d" | "e" | "f"
interface someObject {
foo: string
}
type Data<K> = K extends someTypes ? string : someObject
const doSomething = <K extends someTypes|otherTypes>(key:K, data: Data<K>) => {
switch (key) {
case "b":
console.log(data.length);
break;
case "e":
console.log(data.foo);
break;
}
}
我想要实现的是,对于某些键值,数据具有一种形状,而另一些则具有另一种形状。如果这会超载签名将是这些中的任何一个:
const doSomething = (key: someTypes, data: string) => { }
const doSomething = (key: otherTypes, data: someObject) => { }
解决方案
这里的问题是类型参数K
不能用控制流(switch
)缩小。一个例子:
function fooGeneric<T extends "a" | "b">(t: T) {
if (t === "a") {
t // t is still T extends "a" | "b"
}
}
function fooConcrete(t: "a" | "b") {
if (t === "a") {
t // t is now "a" as expected
}
}
条件类型Data<K>
也不会缩小,所以 TS 不知道函数参数在语句data
分支中的样子。switch
解决方案:在这里只使用类型断言是好的和安全的,因为您已经检查了key
.
const doSomething = <K extends someTypes|otherTypes>(key:K, data: Data<K>) => {
switch (key) {
case "b":
console.log((data as Data<"b">).length);
break;
case "e":
console.log((data as Data<"e">).foo);
break;
}
}
或者,您可以doSomething
具体化并使用映射Data
类型(这个会改变函数签名):
type DataAlt = { [K in someTypes]: string } & { [K in otherTypes]: someObject }
const doSomethingAlt = (key: keyof DataAlt, data: DataAlt) => {
switch (key) {
case "b":
const resB = data[key] // const resB: string
resB.length // ✅
break;
case "e":
const resE = data[key] // const resE: someObject
resE.foo // ✅
break;
}
}
推荐阅读
- android - Storage Access Framework doesn't show cloud roots when using ACTION_OPEN_DOCUMENT_TREE
- php - PHP将图像从url复制到文件夹
- .net - x:Reference "" 不是属性 "IsVisible" 的有效值
- kotlin - Kotlin 允许在函数中定义数据类,为什么?
- java - java spring 2.0中如何配置jasypt?
- firebase - 用于 Flutter 桌面嵌入的 Firebase 身份验证插件
- javascript - 如何使用不同文件中的 Socket.IO 监听特定事件?
- angularjs - 在带有过滤器的 AngularJS 中使用 ng-repeat 打印表
- c++ - 使用 devenv 命令行构建 Visual Studio 解决方案
- python - python groupby 类别列创建新的计数列