diff --git a/bindings/declarations.go b/bindings/declarations.go index 19dacc1..4fb74eb 100644 --- a/bindings/declarations.go +++ b/bindings/declarations.go @@ -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 { @@ -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" diff --git a/testdata/union/union.go b/testdata/union/union.go index bd228f3..9171f14 100644 --- a/testdata/union/union.go +++ b/testdata/union/union.go @@ -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 } diff --git a/testdata/union/union.ts b/testdata/union/union.ts index e0282cc..15f2eb1 100644 --- a/testdata/union/union.ts +++ b/testdata/union/union.ts @@ -1,7 +1,7 @@ // Code generated by 'guts'. DO NOT EDIT. // From union/union.go -export interface Repeated { +export interface Repeated { readonly Value: T; }