Skip to content
Merged
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
43 changes: 28 additions & 15 deletions bindings/declarations.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package bindings

import (
"fmt"
"reflect"
)

// DeclarationType is any type that can exist at the top level of a AST.
// Meaning it can be serialized into valid Typescript.
type DeclarationType interface {
Expand Down Expand Up @@ -69,23 +64,41 @@ func (p *TypeParameter) isNode() {}

// Simplify removes duplicate type parameters
func Simplify(p []*TypeParameter) ([]*TypeParameter, error) {
params := make([]*TypeParameter, 0, len(p))
exists := make(map[string]*TypeParameter)
params := []*TypeParameter{}
set := make(map[string]bool)
for _, tp := range p {
if found, ok := exists[tp.Name.Ref()]; ok {
// Compare types, make sure they are the same
equal := reflect.DeepEqual(found, tp)
if !equal {
return nil, fmt.Errorf("type parameter %q already exists with different type", tp.Name)
ref := tp.Name.Ref()
if _, ok := set[ref]; !ok {
params = append(params, tp)
set[ref] = true

if union, ok := tp.Type.(*UnionType); ok {
simplifyUnionLiterals(union)
}
continue
}
params = append(params, tp)
exists[tp.Name.Ref()] = tp
}
return params, nil
}

func simplifyUnionLiterals(union *UnionType) *UnionType {
types := []ExpressionType{}
literalSet := map[string]bool{}
for _, arg := range union.Types {
switch v := arg.(type) {
case *LiteralKeyword:
key := v.String()
if _, ok := literalSet[key]; !ok {
literalSet[key] = true
types = append(types, arg)
}
default:
types = append(types, arg)
}
}
union.Types = types
return union
}

// VariableStatement is a top level declaration of a variable
// var foo: string = "bar"
// const foo: string = "bar"
Expand Down
1 change: 0 additions & 1 deletion testdata/union/union.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ type UnionConstraint[T string | int64] struct {
}

// Repeated constraints are redundant
// TODO: Write a mutation to remove redundant constraints
type Repeated[T string | string | int64 | uint64] struct {
Value T
}
Comment on lines 8 to 10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a non-literal type as well, as the simplify change only dedupes literals. An eventual change might be to dedupe these as well 🤷

Suggested change
type Repeated[T string | string | int64 | uint64] struct {
Value T
}
type Foo struct{}
type Repeated[T string | string | int64 | uint64 | Foo | Foo] struct {
Value T
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that but Go failed to type-check because it's invalid code. Can't define the same type twice as generic constraint

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL 👍

2 changes: 1 addition & 1 deletion testdata/union/union.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Code generated by 'guts'. DO NOT EDIT.

// From union/union.go
export interface Repeated<T extends string | string | number | number> {
export interface Repeated<T extends string | number> {
readonly Value: T;
}

Expand Down