Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/effect-app-upstream-refresh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@effect/tsgo": patch
---

Refresh the `typescript-go` submodule to the latest upstream (`@typescript/native-preview@7.0.0-dev.20260707.2`, commit `9977d6d`) and cut a new effect-app binary release (`7.0.0-dev+effect-app.10`).

- All `_patches/` apply cleanly against the new upstream, including the gated `.d.ts` schema-facade emitter (`028`–`032`).
- Bump the effect-app version suffix to `.10` so the GitHub binary release is distinguishable from the prior `.9` (which shipped the older upstream).
283 changes: 283 additions & 0 deletions _patches/028-checker-emitresolver-effect-schema.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
diff --git a/internal/checker/emitresolver.go b/internal/checker/emitresolver.go
index 7bf3719e5..b4c50f58c 100644
--- a/internal/checker/emitresolver.go
+++ b/internal/checker/emitresolver.go
@@ -12,6 +12,7 @@ import (
"github.com/microsoft/typescript-go/internal/jsnum"
"github.com/microsoft/typescript-go/internal/nodebuilder"
"github.com/microsoft/typescript-go/internal/printer"
+ "github.com/microsoft/typescript-go/internal/scanner"
)

var _ printer.EmitResolver = (*EmitResolver)(nil)
@@ -1043,6 +1044,270 @@ func (r *EmitResolver) CreateTypeOfExpression(emitContext *printer.EmitContext,
return requestNodeBuilder.SerializeTypeForExpression(expression, enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals, internalFlags, tracker)
}

+func (r *EmitResolver) CreateTypeOfTypeNode(emitContext *printer.EmitContext, typeNode *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ typeNode = emitContext.ParseNode(typeNode)
+ if typeNode == nil {
+ return emitContext.Factory.NewKeywordTypeNode(ast.KindAnyKeyword)
+ }
+
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ requestNodeBuilder := NewNodeBuilder(r.checker, emitContext)
+ return requestNodeBuilder.TypeToTypeNode(r.checker.getTypeFromTypeNode(typeNode), enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals, internalFlags, tracker)
+}
+
+func (r *EmitResolver) CreateTypeLiteralOfTypeNode(emitContext *printer.EmitContext, typeNode *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ typeNode = emitContext.ParseNode(typeNode)
+ if typeNode == nil {
+ return nil
+ }
+
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ return r.createTypeLiteralOfType(emitContext, r.checker.getTypeFromTypeNode(typeNode), enclosingDeclaration, flags, internalFlags, tracker)
+}
+
+func (r *EmitResolver) CreateTypeLiteralOfClassDeclaration(emitContext *printer.EmitContext, declaration *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ declaration = emitContext.ParseNode(declaration)
+ if declaration == nil {
+ return nil
+ }
+
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ if schemaType := r.getTypeOfClassSchemaProperty(declaration, "Type"); schemaType != nil {
+ return r.createTypeLiteralOfType(emitContext, schemaType, enclosingDeclaration, flags, internalFlags, tracker)
+ }
+ symbol := r.checker.getSymbolOfDeclaration(declaration)
+ if symbol == nil {
+ return nil
+ }
+ return r.createTypeLiteralOfType(emitContext, r.checker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, flags, internalFlags, tracker)
+}
+
+func (r *EmitResolver) CreateTypeLiteralOfClassStaticProperty(emitContext *printer.EmitContext, declaration *ast.Node, propertyName string, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ declaration = emitContext.ParseNode(declaration)
+ if declaration == nil {
+ return nil
+ }
+
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ propertyType := r.getTypeOfClassSchemaProperty(declaration, propertyName)
+ if propertyType == nil {
+ return nil
+ }
+ return r.createTypeLiteralOfType(emitContext, propertyType, enclosingDeclaration, flags, internalFlags, tracker)
+}
+
+func (r *EmitResolver) CreateMakeTypeOfClassDeclaration(emitContext *printer.EmitContext, declaration *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ declaration = emitContext.ParseNode(declaration)
+ if declaration == nil {
+ return nil
+ }
+
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ makeType := r.getTypeOfClassSchemaProperty(declaration, "~type.make.in")
+ typeType := r.getTypeOfClassSchemaProperty(declaration, "Type")
+ if makeType == nil || typeType == nil {
+ return nil
+ }
+ return r.createMakeTypeOfTypes(emitContext, makeType, typeType, enclosingDeclaration, flags, internalFlags, tracker)
+}
+
+func (r *EmitResolver) CreateTypeOfClassStaticProperty(emitContext *printer.EmitContext, declaration *ast.Node, propertyName string, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ declaration = emitContext.ParseNode(declaration)
+ if declaration == nil {
+ return nil
+ }
+
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ propertyType := r.getTypeOfClassSchemaProperty(declaration, propertyName)
+ if propertyType == nil {
+ propertyType = r.getTypeOfClassStaticProperty(declaration, propertyName)
+ }
+ if propertyType == nil {
+ return nil
+ }
+ // Emit the decoded property (Type/Encoded/Make/Fields) as a fully-expanded static
+ // type literal instead of the deferred mapped helper (e.g. `Struct.ReadonlySide<…,
+ // "Encoded">`) the node builder would otherwise reference — matching the struct-facade
+ // path. Keeps the generated namespace interfaces static and avoids re-instantiating
+ // the mapped helper at every use site. Non-object properties (service channels resolve
+ // to `never`, Make can be a void union) keep their direct node form.
+ // Expand only plain data objects. A callable type (e.g. the base's `mapFields`
+ // method, or `copy`) is also `TypeFlagsObject` but has no enumerable properties —
+ // expanding it would collapse the call signatures to `{}`, so leave those to the
+ // node builder which preserves the signature.
+ if propertyType.flags&TypeFlagsObject != 0 && len(r.checker.getPropertiesOfType(propertyType)) > 0 {
+ return r.createTypeLiteralOfType(emitContext, propertyType, enclosingDeclaration, flags, internalFlags, tracker)
+ }
+ requestNodeBuilder := NewNodeBuilder(r.checker, emitContext)
+ return requestNodeBuilder.TypeToTypeNode(propertyType, enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals|nodebuilder.FlagsUseFullyQualifiedType, internalFlags, tracker)
+}
+
+func (r *EmitResolver) getTypeOfClassSchemaProperty(declaration *ast.Node, propertyName string) *Type {
+ schemaExpression := getClassSchemaExpression(declaration)
+ if schemaExpression == nil {
+ return nil
+ }
+ return r.getTypeOfSchemaExpressionProperty(schemaExpression, propertyName)
+}
+
+func (r *EmitResolver) getTypeOfSchemaExpressionProperty(schemaExpression *ast.Node, propertyName string) *Type {
+ schemaType := r.checker.getTypeOfExpression(schemaExpression)
+ property := r.checker.getPropertyOfType(schemaType, propertyName)
+ if property == nil {
+ return nil
+ }
+ return r.checker.GetTypeOfSymbolAtLocation(property, schemaExpression)
+}
+
+// Like CreateTypeOfClassStaticProperty, but for a `const X = S.Struct(...)` schema value:
+// reads propertyName (Encoded / Type / ~type.make.in / DecodingServices / ...) off the type
+// of the const's initializer and serializes the resolved type. Serializing the resolved type
+// keeps `never` as `never` and never synthesizes references that could fail to resolve.
+func (r *EmitResolver) CreateTypeOfStructSchemaProperty(emitContext *printer.EmitContext, declaration *ast.Node, propertyName string, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ declaration = emitContext.ParseNode(declaration)
+ if declaration == nil || !ast.IsVariableDeclaration(declaration) || declaration.AsVariableDeclaration().Initializer == nil {
+ return nil
+ }
+ r.checkerMu.Lock()
+ defer r.checkerMu.Unlock()
+ propertyType := r.getTypeOfSchemaExpressionProperty(declaration.AsVariableDeclaration().Initializer, propertyName)
+ if propertyType == nil {
+ return nil
+ }
+ // Emit the decoded property (Type/Encoded/Make/Fields) as a fully-expanded static
+ // type literal — the same shape the class/request facades produce — instead of the
+ // deferred mapped type (e.g. `Struct.ReadonlySide<…, "Type">`) the node builder would
+ // otherwise reference. This keeps the generated `interface X { … }` static and avoids
+ // re-instantiating the mapped helper at every use site. Non-object properties (the
+ // service channels resolve to `never`) keep their direct node form.
+ // Expand only plain data objects. A callable type (e.g. the base's `mapFields`
+ // method, or `copy`) is also `TypeFlagsObject` but has no enumerable properties —
+ // expanding it would collapse the call signatures to `{}`, so leave those to the
+ // node builder which preserves the signature.
+ if propertyType.flags&TypeFlagsObject != 0 && len(r.checker.getPropertiesOfType(propertyType)) > 0 {
+ return r.createTypeLiteralOfType(emitContext, propertyType, enclosingDeclaration, flags, internalFlags, tracker)
+ }
+ structNodeBuilder := NewNodeBuilder(r.checker, emitContext)
+ return structNodeBuilder.TypeToTypeNode(propertyType, enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals|nodebuilder.FlagsUseFullyQualifiedType, internalFlags, tracker)
+}
+
+func getClassSchemaExpression(declaration *ast.Node) *ast.Node {
+ if declaration == nil || !ast.IsClassDeclaration(declaration) || declaration.AsClassDeclaration().HeritageClauses == nil || len(declaration.AsClassDeclaration().HeritageClauses.Nodes) == 0 {
+ return nil
+ }
+ heritageClause := declaration.AsClassDeclaration().HeritageClauses.Nodes[0]
+ if heritageClause == nil || len(heritageClause.AsHeritageClause().Types.Nodes) == 0 {
+ return nil
+ }
+ expression := heritageClause.AsHeritageClause().Types.Nodes[0].AsExpressionWithTypeArguments().Expression
+ if expression == nil || !ast.IsCallExpression(expression) || expression.AsCallExpression().Arguments == nil || len(expression.AsCallExpression().Arguments.Nodes) == 0 {
+ return nil
+ }
+ return expression.AsCallExpression().Arguments.Nodes[0]
+}
+
+func (r *EmitResolver) getTypeOfClassStaticProperty(declaration *ast.Node, propertyName string) *Type {
+ symbol := r.checker.getSymbolOfDeclaration(declaration)
+ if symbol == nil {
+ return nil
+ }
+ staticType := r.checker.getTypeOfSymbol(symbol)
+ property := r.checker.getPropertyOfType(staticType, propertyName)
+ if property == nil {
+ return nil
+ }
+ return r.checker.GetTypeOfSymbolAtLocation(property, declaration)
+}
+
+func (r *EmitResolver) createTypeLiteralOfType(emitContext *printer.EmitContext, typ *Type, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ requestNodeBuilder := NewNodeBuilder(r.checker, emitContext)
+ members := core.Map(r.checker.getPropertiesOfType(typ), func(property *ast.Symbol) *ast.Node {
+ propertyTypeNode := requestNodeBuilder.TypeToTypeNode(r.checker.getTypeOfSymbol(property), enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals|nodebuilder.FlagsUseFullyQualifiedType, internalFlags, tracker)
+ if propertyTypeNode == nil {
+ propertyTypeNode = emitContext.Factory.NewKeywordTypeNode(ast.KindAnyKeyword)
+ }
+ var optionalToken *ast.Node
+ if property.Flags&ast.SymbolFlagsOptional != 0 {
+ optionalToken = emitContext.Factory.NewToken(ast.KindQuestionToken)
+ }
+ return emitContext.Factory.NewPropertySignatureDeclaration(
+ emitContext.Factory.NewModifierList([]*ast.Node{emitContext.Factory.NewModifier(ast.KindReadonlyKeyword)}),
+ createPropertyName(emitContext, property.Name),
+ optionalToken,
+ propertyTypeNode,
+ nil,
+ )
+ })
+ return emitContext.Factory.NewTypeLiteralNode(emitContext.Factory.NewNodeList(members))
+}
+
+func (r *EmitResolver) createMakeTypeOfTypes(emitContext *printer.EmitContext, makeType *Type, typeType *Type, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node {
+ isVoidish := func(typ *Type) bool { return typ.flags&(TypeFlagsVoid|TypeFlagsUndefined) != 0 }
+ var makeTypes []*Type
+ if makeType.flags&TypeFlagsUnion != 0 {
+ makeTypes = makeType.AsUnionType().types
+ }
+ hasVoid := core.Some(makeTypes, isVoidish)
+ objectMakeType := makeType
+ if makeTypes != nil {
+ for _, typ := range makeTypes {
+ if len(r.checker.getPropertiesOfType(typ)) > 0 {
+ objectMakeType = typ
+ break
+ }
+ }
+ }
+ makeProperties := r.checker.getPropertiesOfType(objectMakeType)
+ if len(makeProperties) == 0 {
+ requestNodeBuilder := NewNodeBuilder(r.checker, emitContext)
+ return requestNodeBuilder.TypeToTypeNode(makeType, enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals|nodebuilder.FlagsUseFullyQualifiedType, internalFlags, tracker)
+ }
+ typeProperties := make(map[string]*ast.Symbol)
+ for _, property := range r.checker.getPropertiesOfType(typeType) {
+ typeProperties[property.Name] = property
+ }
+ requestNodeBuilder := NewNodeBuilder(r.checker, emitContext)
+ members := core.Map(makeProperties, func(property *ast.Symbol) *ast.Node {
+ source := property
+ if typeProperty := typeProperties[property.Name]; typeProperty != nil {
+ source = typeProperty
+ }
+ propertyTypeNode := requestNodeBuilder.TypeToTypeNode(r.checker.getTypeOfSymbol(source), enclosingDeclaration, flags|nodebuilder.FlagsMultilineObjectLiterals|nodebuilder.FlagsUseFullyQualifiedType, internalFlags, tracker)
+ if propertyTypeNode == nil {
+ propertyTypeNode = emitContext.Factory.NewKeywordTypeNode(ast.KindAnyKeyword)
+ }
+ var optionalToken *ast.Node
+ if property.Flags&ast.SymbolFlagsOptional != 0 {
+ optionalToken = emitContext.Factory.NewToken(ast.KindQuestionToken)
+ }
+ return emitContext.Factory.NewPropertySignatureDeclaration(
+ emitContext.Factory.NewModifierList([]*ast.Node{emitContext.Factory.NewModifier(ast.KindReadonlyKeyword)}),
+ createPropertyName(emitContext, property.Name),
+ optionalToken,
+ propertyTypeNode,
+ nil,
+ )
+ })
+ literal := emitContext.Factory.NewTypeLiteralNode(emitContext.Factory.NewNodeList(members))
+ if hasVoid {
+ return emitContext.Factory.NewUnionTypeNode(emitContext.Factory.NewNodeList([]*ast.Node{literal, emitContext.Factory.NewKeywordTypeNode(ast.KindVoidKeyword)}))
+ }
+ return literal
+}
+
+func createPropertyName(emitContext *printer.EmitContext, name string) *ast.Node {
+ if scanner.IsIdentifierText(name, core.LanguageVariantStandard) {
+ return emitContext.Factory.NewIdentifier(name)
+ }
+ return emitContext.Factory.NewStringLiteral(name, ast.TokenFlagsNone)
+}
+
func (r *EmitResolver) CreateLateBoundIndexSignatures(emitContext *printer.EmitContext, container *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) []*ast.Node {
container = emitContext.ParseNode(container)
r.checkerMu.Lock()
18 changes: 18 additions & 0 deletions _patches/029-printer-emitresolver-effect-schema.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
diff --git a/internal/printer/emitresolver.go b/internal/printer/emitresolver.go
index 189fe88cc..e617e1171 100644
--- a/internal/printer/emitresolver.go
+++ b/internal/printer/emitresolver.go
@@ -123,6 +123,13 @@ type EmitResolver interface {
CreateTypeParametersOfSignatureDeclaration(emitContext *EmitContext, signatureDeclaration *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) []*ast.Node
CreateLiteralConstValue(emitContext *EmitContext, node *ast.Node, tracker nodebuilder.SymbolTracker) *ast.Node
CreateTypeOfExpression(emitContext *EmitContext, expression *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateTypeOfTypeNode(emitContext *EmitContext, typeNode *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateTypeLiteralOfTypeNode(emitContext *EmitContext, typeNode *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateTypeLiteralOfClassDeclaration(emitContext *EmitContext, declaration *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateTypeLiteralOfClassStaticProperty(emitContext *EmitContext, declaration *ast.Node, propertyName string, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateMakeTypeOfClassDeclaration(emitContext *EmitContext, declaration *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateTypeOfClassStaticProperty(emitContext *EmitContext, declaration *ast.Node, propertyName string, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
+ CreateTypeOfStructSchemaProperty(emitContext *EmitContext, declaration *ast.Node, propertyName string, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
CreateLateBoundIndexSignatures(emitContext *EmitContext, container *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) []*ast.Node
TryJSTypeNodeToTypeNode(emitContext *EmitContext, typeNode *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node
}
Loading