v1.4.0: generic Stream[T] — typed stream messages, drop (T, *Stream, error)

- Stream[T]: Send(v T) type-safe; message type recovered from the
  instantiated Send signature (reflect has no type-args API)
- method signatures reduced to (error), (T, error), (*Stream[T], error);
  the (T, *Stream, error) first-message form is gone — send it via Send
- return T and stream message T now run checkType at bind time
  (Stream[any] remains the explicit untyped escape hatch)
- generated clients: TS onMessage: (data: T); Go <-chan T
- fix vacuous panic assertions (fmt.Sprint(nil) -> "<nil>") in
  hardening/route test catch helpers

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
2026-09-19 15:39:41 +08:00
co-authored by Devin
parent 81d36f827e
commit 84c11c6fde
15 changed files with 184 additions and 117 deletions
+7 -7
View File
@@ -70,18 +70,18 @@ func (ctx GenTs) genService(svc *genSvc, serviceContext *genServiceType) {
returnType := gm.sig.Out(0)
if gm.isStream {
serviceContext.IsIncludeStream = true
if returnType == streamType {
genericTypeText = "any"
returnValueText = "void"
} else {
t := firstLetterToLower(ctx.typeToTemplateType(returnType))
returnValueText = "void"
if msgT := streamMsgType(returnType); msgT != nil && msgT.Kind() != reflect.Interface {
t := firstLetterToLower(ctx.typeToTemplateType(msgT))
if !strings.Contains(t, "[]") && strings.Contains(t, "[") {
genericTypeText = getGenericTypeName(t) + parseGenericTypeParams(t)
} else {
genericTypeText = t
}
returnValueText = "void"
nestedImports = ctx.genReturnTypes(returnType, nestedImports)
nestedImports = ctx.genReturnTypes(msgT, nestedImports)
} else {
// Stream[any]:消息类型由运行期决定,客户端回调给 any
genericTypeText = "any"
}
} else {
serviceContext.IsIncludeRequest = true