Skip to content

Commit 8032d06

Browse files
committed
add basic tuple support
1 parent e428755 commit 8032d06

File tree

10 files changed

+101
-21
lines changed

10 files changed

+101
-21
lines changed

bindings/bindings.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ func (b *Bindings) ToTypescriptExpressionNode(ety ExpressionType) (*goja.Object,
6666
siObj, err = b.LiteralKeyword(ety)
6767
case *ReferenceType:
6868
siObj, err = b.Reference(ety)
69+
case *TupleType:
70+
siObj, err = b.Tuple(ety.Length, ety.Node)
6971
case *ArrayType:
7072
siObj, err = b.Array(ety.Node)
7173
case *UnionType:
@@ -316,6 +318,24 @@ func (b *Bindings) Array(arrType ExpressionType) (*goja.Object, error) {
316318
return res.ToObject(b.vm), nil
317319
}
318320

321+
func (b *Bindings) Tuple(length int, tupleType ExpressionType) (*goja.Object, error) {
322+
tuple, err := b.f("homogeneousTupleType")
323+
if err != nil {
324+
return nil, err
325+
}
326+
327+
siObj, err := b.ToTypescriptExpressionNode(tupleType)
328+
if err != nil {
329+
return nil, fmt.Errorf("array type: %w", err)
330+
}
331+
332+
res, err := tuple(goja.Undefined(), b.vm.ToValue(length), siObj)
333+
if err != nil {
334+
return nil, xerrors.Errorf("call arrayType: %w", err)
335+
}
336+
return res.ToObject(b.vm), nil
337+
}
338+
319339
func (b *Bindings) Alias(alias *Alias) (*goja.Object, error) {
320340
aliasFunc, err := b.f("aliasDecl")
321341
if err != nil {

bindings/expressions.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,23 @@ func Reference(name Identifier, args ...ExpressionType) *ReferenceType {
7070
func (*ReferenceType) isNode() {}
7171
func (*ReferenceType) isExpressionType() {}
7272

73+
type TupleType struct {
74+
// TODO: Technically tuples can be heterogeneous, but golang does not really
75+
// support that. So just assume that all elements are the same type.
76+
Node ExpressionType
77+
Length int
78+
}
79+
80+
func (*TupleType) isNode() {}
81+
func (*TupleType) isExpressionType() {}
82+
83+
func HomogeneousTuple(length int, node ExpressionType) *TupleType {
84+
return &TupleType{
85+
Node: node,
86+
Length: length,
87+
}
88+
}
89+
7390
type ArrayType struct {
7491
Node ExpressionType
7592
}

bindings/walk/walk.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ func Walk(v Visitor, node bindings.Node) {
2929
walkList(v, n.Elements)
3030
case *bindings.ArrayType:
3131
Walk(v, n.Node)
32+
case *bindings.TupleType:
33+
Walk(v, n.Node)
3234
case *bindings.Interface:
3335
walkList(v, n.Parameters)
3436
walkList(v, n.Heritage)

convert.go

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -806,42 +806,49 @@ func (ts *Typescript) typescriptType(ty types.Type) (parsedType, error) {
806806
RaisedComments: append(keyType.RaisedComments, valueType.RaisedComments...),
807807
}
808808
return parsed, nil
809-
case *types.Slice, *types.Array:
810-
// Slice/Arrays are pretty much the same.
811-
type hasElem interface {
812-
Elem() types.Type
809+
case *types.Array:
810+
// Arrays are essentially tuples. Fixed length arrays.
811+
underlying, err := ts.typescriptType(ty.Elem())
812+
if err != nil {
813+
return parsedType{}, xerrors.Errorf("array: %w", err)
813814
}
814815

815-
arr, _ := ty.(hasElem)
816+
if ty.Elem().String() == "byte" {
817+
// [32]byte and other similar types are just strings when json marshaled.
818+
// Is this ok? Should this be an opinion?
819+
return simpleParsedType(ptr(bindings.KeywordString)), nil
820+
}
821+
822+
return parsedType{
823+
Value: bindings.HomogeneousTuple(int(ty.Len()), underlying.Value),
824+
TypeParameters: underlying.TypeParameters,
825+
RaisedComments: underlying.RaisedComments,
826+
}, nil
827+
case *types.Slice:
828+
//// Slice/Arrays are pretty much the same.
829+
//type hasElem interface {
830+
// Elem() types.Type
831+
//}
832+
//
833+
//arr, _ := ty.(hasElem)
816834
switch {
817835
// When type checking here, just use the string. You can cast it
818836
// to a types.Basic and get the kind if you want too :shrug:
819-
case arr.Elem().String() == "byte":
837+
case ty.Elem().String() == "byte":
820838
// All byte arrays are strings on the typescript.
821839
// Is this ok?
822-
return simpleParsedType(bindings.Array(ptr(bindings.KeywordString))), nil
840+
return simpleParsedType(ptr(bindings.KeywordString)), nil
823841
default:
824842
// By default, just do an array of the underlying type.
825-
underlying, err := ts.typescriptType(arr.Elem())
843+
underlying, err := ts.typescriptType(ty.Elem())
826844
if err != nil {
827-
return parsedType{}, xerrors.Errorf("array: %w", err)
845+
return parsedType{}, xerrors.Errorf("slice: %w", err)
828846
}
829-
//genValue := ""
830-
//
831-
//if underlying.GenericValue != "" {
832-
// genValue = "Readonly<Array<" + underlying.GenericValue + ">>"
833-
//}
834847
return parsedType{
835848
Value: bindings.Array(underlying.Value),
836849
TypeParameters: underlying.TypeParameters,
837850
RaisedComments: underlying.RaisedComments,
838851
}, nil
839-
//return TypescriptType{
840-
// ValueType: "Readonly<Array<" + underlying.ValueType + ">>",
841-
// GenericValue: genValue,
842-
// AboveTypeLine: underlying.AboveTypeLine,
843-
// GenericTypes: underlying.GenericTypes,
844-
//}, nil
845852
}
846853
case *types.Named:
847854
n := ty

testdata/array/array.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package array
2+
3+
type StaticArray struct {
4+
Numbers [3]int
5+
Slice []int
6+
Hash [32]byte
7+
SliceHash []byte
8+
}

testdata/array/array.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Code generated by 'guts'. DO NOT EDIT.
2+
3+
// From array/array.go
4+
export interface StaticArray {
5+
readonly Numbers: [
6+
number,
7+
number,
8+
number
9+
];
10+
readonly Slice: readonly number[];
11+
readonly Hash: string;
12+
readonly SliceHash: string;
13+
}

testdata/generics/generics.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,5 @@ type UnusedGeneric[B any] struct {
5656
type UseUnused BasicGeneric[UnusedGeneric[int]]
5757
type UseUnusedWithGen[T any] BasicGeneric[UnusedGeneric[T]]
5858
type UseUnusedAlias BasicGeneric[UnusedGeneric[UnusedGeneric[int]]]
59+
60+
type AliasGeneric[A any] = BasicGeneric[A]

testdata/generics/generics.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
// Code generated by 'guts'. DO NOT EDIT.
22

3+
// From codersdk/generics.go
4+
export interface AliasGeneric<A extends any> {
5+
readonly Val: A;
6+
}
7+
38
// From codersdk/generics.go
49
export interface BasicGeneric<A extends any> {
510
readonly Val: A;

typescript-engine/dist/main.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

typescript-engine/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ export function arrayType(node: ts.TypeNode): ts.ArrayTypeNode {
107107
return ts.factory.createArrayTypeNode(node);
108108
}
109109

110+
export function homogeneousTupleType(length: number, node: ts.TypeNode): ts.TupleTypeNode {
111+
const nodes = Array.from({ length }, () => node);
112+
return ts.factory.createTupleTypeNode(nodes);
113+
}
114+
110115
export function aliasDecl(
111116
modifiers: readonly modifierKeys[] | readonly ts.Modifier[] | undefined,
112117
name: ts.Identifier | string,
@@ -248,6 +253,7 @@ module.exports = {
248253
toTypescript: toTypescript,
249254
interfaceDecl: interfaceDecl,
250255
literalKeyword: literalKeyword,
256+
homogeneousTupleType: homogeneousTupleType,
251257
arrayType: arrayType,
252258
aliasDecl: aliasDecl,
253259
typeParameterDeclaration: typeParameterDeclaration,

0 commit comments

Comments
 (0)