TypeSpec @typespec/streams 详解:用 @streamOf 装饰器与 Stream 基类描述流式协议类型

发布时间:2026/11/12 2:34:04

TypeSpec @typespec/streams 详解:用 @streamOf 装饰器与 Stream 基类描述流式协议类型 TypeSpec typespec/streams 详解用 streamOf 装饰器与 Stream 基类描述流式协议类型【免费下载链接】typespec项目地址: https://gitcode.com/GitHub_Trending/ty/typespectypespec/streams是 TypeSpec 官方提供的流式绑定stream bindings库用于在类型层面声明某个 Model 代表一种流协议类型其承载的数据由某个Type描述。本文将围绕 README 中介绍的streamOf装饰器展开先讲安装与基本用法再结合源码剖析装饰器的实现原理、StreamType泛型基类的工作机制以及如何在自己的库或生成器中通过getStreamOf/isStreamAPI 消费这些流信息。读完本文你将能够在 TypeSpec 项目中正确声明流式数据类型、复用Stream基类派生自定义流并了解从 AST 装饰器到程序状态Program state的完整实现链路。1. 安装按 README 的说明通过 npm 安装即可npm install typespec/streams在tspconfig.yaml中引入该库后TypeSpec 编译器会通过tspMain入口加载 lib/main.tsp。从 package.json 可以看到该包以tspMain: lib/main.tsp声明 TypeSpec 入口并在exports的typespec条件中同样指向./lib/main.tsp。注意其engines字段要求 Node.js22.0.0且typespec/compiler是peerDependencies使用时需要确保工作区中的 compiler 版本与之匹配。lib/main.tsp 的内容非常简洁它把三块东西装配成一个完整库import ../dist/src/tsp-index.js; import ./decorators.tsp; import ./types.tsp;第一行导入编译后的 JS 侧实现装饰器实现与$lib库定义第二、三行导入 TypeSpec 声明文件。也就是说这个库是一个典型的TypeSpec 声明 JS 装饰器实现组合extern dec声明在.tsp文件里真正的行为在 src/tsp-index.ts 注册。2.streamOf装饰器2.1 声明与参数streamOf声明于 lib/decorators.tspnamespace TypeSpec.Streams; /** * Specify that a model represents a stream protocol type whose data is described * by Type. * * param type The type that models the underlying data of the stream. */ extern dec streamOf(target: Model, type: unknown);其完整语义与参数如下与 README 的装饰器参考表一致声明签名TypeSpec.Streams.streamOf(type: unknown)应用目标TargetModel参数名称类型说明typeunknown描述该流底层数据underlying data的类型type之所以是unknown而不是Model从测试用例 test/decorators.test.ts 可以看出原因——标量也可以作为流数据streamOf(string) model Blob {}测试断言getStreamOf(program, Blob)返回的对象kind为Scalar、name为string。也就是说流的数据既可以是复杂的model也可以是string、bytes等任意 TypeSpec 类型。2.2 使用示例README 给出的标准示例model Message { id: string; text: string; } streamOf(Message) model Response { body body: string; }这里的语义是Response是一个流协议类型例如一个按帧/按消息推送的流端点它每次产出的数据单元的结构由Message描述。流本身可以额外携带协议字段如body body: string这类传输层描述但每个数据项是什么由streamOf的泛化参数表达。2.3 实现原理装饰器如何存储状态extern dec声明在编译后需要 JS 侧实现来落地。装饰器实现在 src/decorators.tsimport type { Model, Program, Type } from typespec/compiler; import { useStateMap } from typespec/compiler/utils; import type { StreamOfDecorator } from ../generated-defs/TypeSpec.Streams.js; import { StreamStateKeys } from ./lib.js; const [getStreamOf, setStreamOf] useStateMapModel, Type(StreamStateKeys.streamOf); export const $streamOfDecorator: StreamOfDecorator (context, target, type) { setStreamOf(context.program, target, type); }; export function isStream(program: Program, target: Model): boolean { return getStreamOf(program, target) ! undefined; } export { getStreamOf };实现链路可以拆成三步注册状态键。src/lib.ts 用createTypeSpecLibrary创建库定义并声明了一个名为streamOf的程序状态槽export const $lib createTypeSpecLibrary({ name: typespec/streams, diagnostics: {}, state: { streamOf: { description: State for the streamOf decorator. }, }, }); export const { reportDiagnostic, createDiagnostic, stateKeys: StreamStateKeys } $lib;StreamStateKeys.streamOf是这个库专属的状态键保证状态不与别的库冲突。绑定状态映射。useStateMapModel, Type(StreamStateKeys.streamOf)返回一对get/set函数把被装饰的 Model映射为其数据Type存储在Program上。这是 TypeSpec 装饰器向后续阶段如 emit 阶段传递信息的标准方式。执行装饰器。$streamOfDecorator被 src/tsp-index.ts 注册到命名空间TypeSpec.Streams下export const $decorators { TypeSpec.Streams: { streamOf: $streamOfDecorator, }, };编译器在检查到streamOf(Message)时调用该函数把type参数写入状态。对外导出的公共 API 在 src/index.tsexport { $lib } from ./lib.js; export { getStreamOf, isStream } from ./decorators.js; export { $decorators } from ./tsp-index.js;2.4 消费 APIgetStreamOf与isStream其他库例如各种 HTTP 客户端 emitter 或自定义生成器可以在 import 阶段或 emit 阶段查询流信息getStreamOf(program, model)返回被streamOf标记的数据Type若该 Model 未被装饰则返回undefined测试用例已验证这一点。isStream(program, model)便捷判断函数等价于getStreamOf(...) ! undefined。import { getStreamOf, isStream } from typespec/streams; if (isStream(context.program, model)) { const itemType getStreamOf(context.program, model); // itemType 就是 streamOf 里传入的类型 }3.StreamType泛型基类除了装饰器该库还提供了一个开箱即用的泛型模型 lib/types.tspnamespace TypeSpec.Streams; /** * Defines a model that represents a stream protocol type whose data is described * by Type. * * This can be useful when the underlying data type is not relevant, or to serve as * a base type for custom streams. * * template Type The type of the streams data. */ doc() streamOf(Type) model StreamType {}它是自装饰的Stream自身被streamOf(Type)标记而Type是它自己的模板参数。因此派生使用时只需实例化模板即可自动获得流标记。例如测试 test/decorators.test.ts 中验证的场景model Message { id: string, text: string } model CustomStream is StreamMessage {}断言结果为getStreamOf(program, CustomStream) Message。这说明通过is StreamMessage继承时装饰器效果会传递到派生模型上——测试用例名即为 is automatically set on the Stream model。StreamType的官方注释指出了两个适用场景原文直译底层数据类型不重要时直接用Streambytes之类表示这是个流具体数据后面再说作为自定义流的基类像model CustomStream is StreamMessage这样派生再补充自己的协议字段。从源码结构看streamOf作用于模板模型时Type是模板参数符号实例化派生时具体类型如Message会落到派生模型的状态上这也是测试能断言到具体 Model 的原因。4. 包的对外结构与测试整个包结构很小值得逐一确认lib/main.tspTypeSpec 入口装配 JS 实现与两个声明文件lib/decorators.tspextern dec streamOf声明lib/types.tspStreamType泛型基类src/decorators.ts装饰器实现与getStreamOf/isStreamsrc/lib.tscreateTypeSpecLibrary库定义与状态键src/tsp-index.ts$decorators/$lib注册入口src/testing/index.ts对应 package.json 中./testing导出子路径的测试辅助工具generated-defs/TypeSpec.Streams.ts由gen-extern-signature脚本tspd gen-extern-signature生成的 extern 签名类型src/decorators.ts 中StreamOfDecorator类型即来自这里。测试方面test/decorators.test.ts 覆盖了三条关键行为streamOf(string)记录标量数据、未装饰模型返回undefined、派生自StreamMessage的模型自动携带流标记。测试通过 test/test-host.ts 提供的Tester基于 src/testing/index.ts编译内联代码完成。5. 小结typespec/streams提供了一套最小但完整的流式类型原语streamOf装饰器把流的数据项类型挂到 Program 状态上StreamType泛型模型提供可继承的流基类getStreamOf/isStream则供下游库查询使用。它的当前版本为 0.86.0见 package.json要求 Node.js 22且自 0.61.0 起作为新增核心包随仓库演进参见 CHANGELOG.md。对于需要在 TypeSpec 中建模流式端点、或构建消费流语义的 emitter 的开发者这组 API 就是接入点。【免费下载链接】typespec项目地址: https://gitcode.com/GitHub_Trending/ty/typespec创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/10 11:08:26

AEStudio使用手册:脚本预设模板与渲染管理提升AE效率

在动态设计这个行当里泡久了,你会发现一个挺反直觉的现象:真正拖慢进度的往往不是AE本身的渲染速度,而是那些反反复复的机械动作——打开项目、翻文件夹找脚本、回忆上次用的预设参数、把模板里的素材替换成自己的。AEStudio这个名字听起来像…

2026/11/9 23:09:23

直线拟合三大算法:最小二乘法、RANSAC与Hough变换实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/10 11:08:08

FPGA SoC开发板Linux下7寸触摸屏驱动调试全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/12 8:24:31

黎平特种作业操作证怎么考不花冤枉钱 电子证书真靠谱吗

黎平特种作业操作证怎么考不花冤枉钱 电子证书真靠谱吗 怕考不过白交培训费?现在很多人想考特种作业操作证,但又担心培训机构套路多、考试难、证书没用,最后钱花了还拿不到证。其实只要方法对了,考特种作业操作证完全可以避开这些坑,尤其是像【黎平特种…

2026/11/12 8:24:31

上学给办电工证吗千万别踩坑实操考试考什么

上学给办电工证吗千万别踩坑实操考试考什么 怕考不过白交培训费?别再被那些“包过”“代考”坑了!现在很多人都在问“上学给办电工证吗”,但真正了解电工证报考流程、实操考试内容和背后风险的人却不多。尤其是一些学生或者刚转行的打工者,误以为上学期间…

2026/11/12 8:24:31

电工证正规考取步骤图+考前押题全攻略,实操考试心里没底怕挂科

电工证正规考取步骤图+考前押题全攻略,实操考试心里没底怕挂科 你不是一个人在战斗,很多人第一次接触电工证实操考试时,都担心自己会不会因为操作不熟练挂科。尤其是像南阳卧龙区这样的地方,实操考试对细节要求高,一个操作失误就可能被淘汰。但别担心,…

2026/11/12 8:24:31

崇阳考电工证多少钱?别被中介坑了,这样选培训机构最靠谱

崇阳考电工证多少钱?别被中介坑了,这样选培训机构最靠谱 你是不是也遇到过这种情况,想考电工证,但不知道该去哪报名,怕被中介骗钱?崇阳考电工证多少钱?这事儿真得仔细琢磨一下,别一不小心花了冤枉钱还拿不到证。今天就从头到尾告诉你,怎么在崇阳选对…

2026/11/12 8:19:30

德州电工证考试在哪里网上查询别被坑!新手报名避坑指南

德州电工证考试在哪里网上查询别被坑!新手报名避坑指南 不知道去哪报名怕被中介坑,尤其是像德州电工证考试在哪里这种信息,网上一搜五花八门,让人眼花缭乱。今天就从实战经验出发,告诉你德州电工证到底该怎么考,怎么避坑,还能帮你搞清楚网上查询的流程…

2026/11/11 12:42:59

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/12 0:04:01

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘

工地太忙根本没时间复习考试?学习电工证到哪里学通过率揭秘 工地太忙根本没时间复习考试?你不是一个人。作为一名在南阳卧龙区干了七八年市政公用工程的电工,我深知这个问题的现实性。电工证不仅是工作的“入场券”,更是职业发展的“通行证”,但备考过程…

2026/11/12 0:04:01

双流电工证考别怕挂科!郑州报考避坑指南全攻略

双流电工证考别怕挂科!郑州报考避坑指南全攻略 实操考试心里没底怕挂科?双流电工证考在郑州报名,很多人因为不了解流程、准备不充分,白白浪费时间和金钱。作为三门峡应届工程类毕业生,我也曾经历过这样的焦虑。今天就从零开始,手把手教你如何避开郑州报…

2026/11/12 0:04:01

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少

之前考的证在外省能不能转过来 怎么报名考电工证培训价格多少 之前考的证在外省能不能转过来?这个问题确实让不少准备换城市工作的朋友犯了难,尤其像电工证这种实操性很强的证书,很多人担心跨省后证书能不能继续用。其实,只要符合相关流程,是可以顺利转…

2026/11/11 20:27:01

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑