提问人:awdk 提问时间:11/1/2022 最后编辑:awdk 更新时间:11/2/2022 访问量:150
如何通过条件类型检查区分不同的函数签名?
How to distinguish different functions signature with conditional type checks?
问:
我想在条件类型检查中区分以下函数类型:
type SyncFn = () => void;
type AsyncFn = (data: number) => Promise<void>;
type SyncFnWithArg = (data: number) => void;
因此,我可以使用 @Titian Cernicova-Dragomir 发布的 KeyOfType,并在给定接口中获取与给定类型匹配的密钥。
我尝试了以下方法:
type SyncFn = () => void;
type AsyncFn = (data: number) => Promise<void>;
type SyncFnWithArg = (data: number) => void;
interface Foo {
a?: string;
b?: number;
c: number;
d: string;
f1?: SyncFn;
f2?: AsyncFn;
f3?: SyncFnWithArg;
}
// note: `KeyOfType` from https://stackoverflow.com/questions/49752151/typescript-keyof-returning-specific-type
type KeyOfType<T, V> = keyof { [P in keyof T as T[P] extends V? P: never]: any }
type KeyOfTypeOptionalIncluded<T, Condition> = KeyOfType<T, Condition | undefined>
let onlyStrings: KeyOfTypeOptionalIncluded<Foo, string>;
onlyStrings = 'a' // ✅ working as expected 🎉
onlyStrings = 'b' // ✅ erroring out as expected 🎉
onlyStrings = 'd' // ✅ working as expected 🎉
let onlySyncFn: KeyOfTypeOptionalIncluded<Foo, SyncFn>;
onlySyncFn = 'f1' // ✅ working as expected 🎉
onlySyncFn = 'f2' // ✅ erroring out as expected 🎉
onlySyncFn = 'f3' // ✅ erroring out as expected 🎉
let onlyAsyncFn: KeyOfTypeOptionalIncluded<Foo, AsyncFn>;
onlyAsyncFn = 'f1' // ✅ erroring out as expected 🎉
onlyAsyncFn = 'f2' // ✅ working as expected 🎉
onlyAsyncFn = 'f3' // ✅ erroring out as expected 🎉
let onlySyncFnWithArg: KeyOfTypeOptionalIncluded<Foo, SyncFnWithArg>;
onlySyncFnWithArg = 'f1' // 😭 should error out 😭
onlySyncFnWithArg = 'f2' // 😭 should error out 😭
onlySyncFnWithArg = 'f3' // ✅ working as expected 🎉
问题是它被输入为,而它应该是......onlySyncFnWithArg
"f1" | "f2" | "f3"
"f3"
我还注意到,如果我修改并删除它的参数,那么我会遇到更多问题,因为 的类型定义现在是不正确的,因为现在它不仅仅是在上面的第一个 TS Playground 中。AsyncFn
onlySyncFn
"f1" | "f2"
"f1"
我想这与打字稿中的函数重载是如何完成的有关,但我真的不知道,所以这就是我寻求帮助的原因......也许它不相关,但是我们能够在 TS 中进行这样的函数类型区分吗?
答:
1赞
Robby Cornelissen
11/1/2022
#1
可以通过更改类型来解决此问题,如下所示:KeyOfType
- 检查类型关系的两个方向 ( 和 ):
A extends B
B extends A
- 将条件类型子句中使用的类型包装在元组 () 中。
[A] extends [B]
type KeyOfType<T, V> = keyof {
[P in keyof T as [T[P]] extends [V]
? [V] extends [T[P]]
? P
: never
: never
]: any
}
在这里找到一个 playground 示例,并在这里找到一个有趣的讨论,讨论测试类型相等的各种方法(每种方法都有自己的注意事项)。
评论
0赞
awdk
11/2/2022
哦。。。这是有道理的!!这对我来说是全新的(检查两个方向)!非常感谢!🎉
评论