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

发布时间:2026/9/18 15:47:28

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/9/18 15:47:28

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

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

2026/9/18 15:42:28

直线拟合三大算法:最小二乘法、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/9/18 15:42:28

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/9/18 16:42:36

同一把 TaoToken Key,从 GPT-Live-1 切到 Grok Voice Think Fast 2.0 High

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

2026/9/18 16:42:36

工厂仓储数字化:华智WMS落地关键与数据链路优化

简介:这是一份面向工厂仓储物流数字化升级的完整解决方案文档,适合制造企业、商贸流通企业的仓储管理者及信息化实施人员阅读,用于理解WMS(仓储管理系统)如何解决传统仓库现场管理中的先进先出难执行、数据录入滞后、盘…

2026/9/18 16:42:36

OpenCode 长任务切换,TaoToken 给后端鉴权入口

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

2026/9/18 14:13:01

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/18 0:01:09

Google Colab 实战:运行模型、数据加载与报错排查

1. 为什么我劝你先搞懂 Colab 的运行模型1.1 Colab 到底是什么,跟本地跑代码差在哪Google Colab 简单说就是一台跑在浏览器里的 Linux 虚拟机,你打开一个 Notebook,背后就连上了一台带 GPU 的远程机器。你在单元格里敲的每一行 Python&#x…

2026/9/18 0:01:09

C语言数据类型与表达式详解

1. C语言数据与数据类型概述在C语言编程中,数据是程序处理的核心对象。理解数据的分类和特性是掌握C语言的基础。C语言中的数据主要分为四大类:常量、变量、表达式和函数。这些数据类型构成了C语言程序的基本元素,每种类型都有其独特的特性和…

2026/9/18 0:01:09

SQL时间字段指定时间段查询:区间语义、索引与时区避坑

上周排查一个线上问题&#xff0c;用户反馈"昨天的订单一条都没查到"&#xff0c;但数据库里明明躺着两千多条。最后定位下来&#xff0c;不是数据丢了&#xff0c;也不是接口挂了&#xff0c;而是那个查询条件把时间段写成了> 2024-05-20 00:00:00 AND < 2024…

2026/9/18 14:13:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行&#xff0c;Type-C接口算是典型的“看着简单&#xff0c;做起来全坑”的东西。光引脚就24个&#xff0c;高低速信号、电源、控制线全部塞在一个小小的连接器里&#xff0c;如果PCB布局不做规划&#xff0c;打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/18 14:13:02

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/18 14:13:02

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

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

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

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