如何声明TypeScript类型确保数组中函数输入输出类型衔接?
类型声明:确保数组中函数的输入输出类型链式匹配
问题描述
想要声明一个类型,确保数组中某个函数的输出类型与下一个函数的输入类型完全一致。
示例数组:
const mappings = [ (x: EditorState) => editorState.getCurrentContent(x) as ContentState, (x: ContentState) => convertToRaw(x) as RawDraftContentState, (x: RawDraftContentState) => JSON.stringify(x) as string, (x: string) => gzipString(x) ]
该类型大概率需要同时具备递归性与泛型特性。
编辑补充:若能给出覆盖一定长度列表所有可能情况的方案即可,这应该是可行的吧?
解决方案
递归泛型实现方案
我们可以通过递归泛型约束函数数组的链式类型匹配,确保每一个函数的输出与下一个函数的输入类型严格对齐:
// 基础函数类型:接收输入I,返回输出O type Func<I, O> = (input: I) => O; // 递归定义的函数链类型,支持任意长度 type FunctionChain<PrevInput> = [ Func<PrevInput, infer NextOutput>, ...FunctionChain<NextOutput> ] | [];
使用时只需指定初始输入类型,TypeScript会自动校验整个链的类型匹配:
// 声明以EditorState为初始输入的函数链类型 type EditorStateProcessingChain = FunctionChain<EditorState>; // 若函数输入输出不匹配,TypeScript会直接报错 const mappings: EditorStateProcessingChain = [ (x: EditorState) => editorState.getCurrentContent(x) as ContentState, (x: ContentState) => convertToRaw(x) as RawDraftContentState, (x: RawDraftContentState) => JSON.stringify(x) as string, (x: string) => gzipString(x) ];
固定长度覆盖方案
如果不需要支持无限长度,只需覆盖特定范围的函数链长度(比如1-4个函数),可以手动定义不同长度的链类型并合并为联合类型,这种方式类型检查更高效:
type Func<I, O> = (input: I) => O; // 长度为1的函数链 type Chain1<I, O> = [Func<I, O>]; // 长度为2的函数链:中间类型M衔接输入I和输出O type Chain2<I, M, O> = [Func<I, M>, Func<M, O>]; // 长度为3的函数链:两个中间类型衔接 type Chain3<I, M1, M2, O> = [Func<I, M1>, Func<M1, M2>, Func<M2, O>]; // 长度为4的函数链:三个中间类型衔接 type Chain4<I, M1, M2, M3, O> = [Func<I, M1>, Func<M1, M2>, Func<M2, M3>, Func<M3, O>]; // 合并为支持1-4长度的联合类型 type FixedLengthChain<I, FinalOutput> = Chain1<I, FinalOutput> | Chain2<I, infer M, FinalOutput> | Chain3<I, infer M1, infer M2, FinalOutput> | Chain4<I, infer M1, infer M2, infer M3, FinalOutput>;
使用示例:
// 指定初始输入为EditorState,最终输出为gzipString的返回类型 const mappings: FixedLengthChain<EditorState, ReturnType<typeof gzipString>> = [ (x: EditorState) => editorState.getCurrentContent(x) as ContentState, (x: ContentState) => convertToRaw(x) as RawDraftContentState, (x: RawDraftContentState) => JSON.stringify(x) as string, (x: string) => gzipString(x) ];
方案对比
- 递归泛型方案:支持任意长度的函数链,但在链极长时可能出现类型推导性能下降
- 固定长度方案:类型检查速度更快、逻辑更直观,适合提前明确函数链最大长度的场景
内容的提问来源于stack exchange,提问作者Sp Jan
相关产品推荐
相关产品推荐

