From b4fa0e8debe962f7c87fdfcfcb9ccdf4de9f6eaf Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 24 Jul 2025 18:51:30 -0500 Subject: [PATCH] chore: prevent `null` in heritage `extends` expressions This is a temporary workaround to generate valid typescript. This solution is not completely correct, and is subject to future change. --- convert.go | 15 ++++++++++++++- testdata/excludecustom/excludecustom.ts | 2 +- testdata/inheritance/inheritance.go | 7 ++++++- testdata/inheritance/inheritance.ts | 4 ++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/convert.go b/convert.go index 5b9daf8..630c657 100644 --- a/convert.go +++ b/convert.go @@ -650,8 +650,21 @@ func (ts *Typescript) buildStruct(obj types.Object, st *types.Struct) (*bindings // Adding a json struct tag causes the json package to consider // the field unembedded. if field.Embedded() && tag.Get("json") == "" { + // TODO: This prevents an inheritance clause from having a ` | null` in the + // expression. Typescript does not support `null` in the extends clause. + // This is not a perfect solution, and exists as a workaround. + // See https://github.com/coder/guts/issues/40 + fieldType := field.Type() + for i := 0; i < 10; i++ { // Can there be an infinite loop here? + if ptrType, ok := fieldType.(*types.Pointer); ok { + fieldType = ptrType.Elem() + continue + } + break + } + // TODO: Generic args - heritage, err := ts.typescriptType(field.Type()) + heritage, err := ts.typescriptType(fieldType) if err != nil { return tsi, xerrors.Errorf("heritage type: %w", err) } diff --git a/testdata/excludecustom/excludecustom.ts b/testdata/excludecustom/excludecustom.ts index 2b493cf..bff402f 100644 --- a/testdata/excludecustom/excludecustom.ts +++ b/testdata/excludecustom/excludecustom.ts @@ -4,4 +4,4 @@ export interface Public { readonly PublicString: string; readonly PublicInt: number; -} \ No newline at end of file +} diff --git a/testdata/inheritance/inheritance.go b/testdata/inheritance/inheritance.go index ed4339a..c70154e 100644 --- a/testdata/inheritance/inheritance.go +++ b/testdata/inheritance/inheritance.go @@ -5,6 +5,11 @@ type Foo struct { GenBar[string] } +type FooBarPtr struct { + *Bar + GenBar[string] +} + type Bar struct { BarField int } @@ -17,7 +22,7 @@ type GenBar[T comparable] struct { // See: https://go.dev/play/p/-p6QYmY8mtR type FooBuzz struct { Buzz `json:"foo"` // Json tag changes the inheritance - Bazz string `json:"bazz"` + Bazz string `json:"bazz"` } type Buzz struct { diff --git a/testdata/inheritance/inheritance.ts b/testdata/inheritance/inheritance.ts index 262ccaa..c8d623a 100644 --- a/testdata/inheritance/inheritance.ts +++ b/testdata/inheritance/inheritance.ts @@ -16,6 +16,10 @@ export type Comparable = string | number | boolean; export interface Foo extends Bar, GenBar { } +// From codersdk/inheritance.go +export interface FooBarPtr extends Bar, GenBar { +} + // From codersdk/inheritance.go export interface FooBuzz { readonly foo: Buzz;