TypeSpec 是什么,和 C# 有什么关系?
TypeSpec 本身不是 C# 的一部分,它是微软推出的、基于 TypeScript 的接口定义语言(IDL),用来描述 API(尤其是 RESTful 服务)的结构。它不直接生成 C# 类型,但可通过插件(如
@typespec/openapi3+
@typespec/csharp)输出 C# 客户端或服务端代码。关键点是:TypeSpec 不编译进运行时,它只在设计/生成阶段起作用。
如果你期望“写个 .tsp 文件就自动编译成可运行的 C# 项目”,那会失望——它更像 Swagger + TypeScript 的增强版,目标是统一契约、驱动多语言代码生成。
如何用 TypeSpec 定义一个简单 API 并生成 C# 客户端?
先确保安装了 Node.js 和 TypeSpec CLI:
npm install -g @typespec/cli
创建
main.tsp,定义一个待生成的 API:
import "@typespec/http";
import "@typespec/openapi3";
import "@typespec/csharp";
<p>@service({title: "TodoService"})
namespace TodoApi {
@route("/todos")
@get
op listTodos(): Todo[];</p><p>@route("/todos/{id}")
@get
op getTodo(@path id: string): Todo;
}</p><p>model Todo {
@key id: string;
name: string;
completed: boolean;
}然后执行生成命令(需先安装
@typespec/csharp插件):
npx tsp compile . --emit @typespec/csharp --option "@typespec/csharp.emitter-output-dir=./GeneratedClient"
生成的 C# 代码默认包含
TodoApiClient、
Todo模型等,使用的是
System.Net.Http和
System.Text.Json,不依赖第三方 HTTP 客户端库。
@typespec/csharp目前仍为预览版,生成的代码可能缺少部分特性(如分页支持、自定义序列化器钩子) 必须显式导入
@typespec/csharp,否则
--emit会静默失败 路径参数(
@path)、查询参数(
@query)、请求体(
@body)需正确标注,否则生成的 C# 方法签名可能漏参数或类型错误
C# 服务端生成是否可行?
目前(2024 年中)
@typespec/csharp官方仅支持客户端生成(即调用方代码),不生成 ASP.NET Core Controller 或 Minimal API。想用 TypeSpec 驱动服务端,有两条现实路径: 用
@typespec/openapi3导出 OpenAPI JSON,再用
NSwag或
Microsoft.dotnet-openapi工具反向生成服务端骨架(但会丢失 TypeSpec 特有语义,如
@visibility、
@friendlyName) 手动实现 Controller,并用
[ProducesResponseType]等特性对齐 OpenAPI 输出,再通过
tsp compile . --emit @typespec/openapi3验证一致性 社区有实验性插件(如
typespec-csharp-server)尝试生成 Minimal API,但稳定性差、无官方维护,不建议用于生产
换句话说:TypeSpec 当前对 C# 服务端是“契约先行但手写实现”,而非“契约即实现”。
常见报错与绕过方式
运行
tsp compile时容易遇到以下问题:
Error: Cannot resolve emitter "@typespec/csharp"→ 检查是否在项目根目录执行,且
package.json中已声明
@typespec/csharp为 devDependency;不要用全局
npx tsp调用本地插件 生成的 C# 类名含非法字符(如
My-Resource)→ TypeSpec 默认转为 PascalCase,但连字符会被忽略导致冲突(
MyResource和
MyResource),改用
@friendlyName("MyResource") 显式指定
DateTime 字段生成为 DateTimeOffset?而非
DateTime?→ 这是 OpenAPI 3.0 对时间字段的规范行为,若后端强制用
DateTime,需在 C# 客户端手动映射或改用
@type注解配合自定义序列化器
最易被忽略的一点:TypeSpec 的
@doc、
@summary等注释默认不会出现在生成的 C# XML 注释里,需额外配置
--option "@typespec/csharp.include-docs=true"才启用。
