# How to Exclude Specific Go Fields from TypeScript Generation in tsgo

> Learn how to exclude specific Go fields from TypeScript generation using json or tsgo struct tags. Prevent unwanted fields from appearing in your generated TS declarations.

- Repository: [Microsoft/typescript-go](https://github.com/microsoft/typescript-go)
- Tags: how-to-guide
- Published: 2026-04-25

---

**Add a `json:"-"` or `tsgo:"-"` struct tag to any exported Go field to prevent it from appearing in the generated TypeScript declarations.**

The `tsgo` command-line tool in the microsoft/typescript-go repository walks your Go AST and converts exported struct fields into TypeScript interface members. When you need to hide specific fields from the resulting [`.d.ts`](https://github.com/microsoft/typescript-go/blob/main/.d.ts) output—such as sensitive data or internal implementation details—struct tags provide the control mechanism without modifying field visibility in Go.

## How Field Visibility Maps to TypeScript Output

The generator follows the same visibility rules as the Go JSON encoder when deciding which fields appear in the output. In [`internal/transformers/tstransforms/typeeraser.go`](https://github.com/microsoft/typescript-go/blob/main/internal/transformers/tstransforms/typeeraser.go), the AST walker checks each struct field against these criteria:

- **Exported fields** (starting with uppercase letter): Included by default
- **Unexported fields** (starting with lowercase letter): Automatically excluded  
- **Exported fields with omission tags**: Excluded when tagged with `json:"-"` or `tsgo:"-"`

This means any exported field you mark with a dash (`-`) as the first option in its tag will be skipped during TypeScript generation.

## Methods to Exclude Go Fields from TypeScript Output

You have two primary tag-based approaches to suppress field emission, depending on whether you want to affect JSON marshaling simultaneously.

### Using the Standard `json:"-"` Tag

The most common method reuses the standard Go JSON omit marker. When `tsgo` encounters `json:"-"`, it interprets this as a universal "do not emit this field" signal across all external representations.

```go
package model

type User struct {
    ID       int    `json:"id"`
    Name     string `json:"name"`
    Password string `json:"-"`  // Excluded from .d.ts output
}

```

### Using the Custom `tsgo:"-"` Tag

For cases where you want to hide a field only from TypeScript declarations while keeping it in JSON output, use the `tsgo` tag. The generator specifically checks for a tag named `tsgo` and treats `-` as the omit marker.

```go
type Config struct {
    Host      string `json:"host"`
    DebugMode bool   `tsgo:"-"`  // Hidden from TypeScript, visible in Go
}

```

## Practical Code Examples

Here is a complete example showing multiple exclusion patterns in a single struct:

```go
package model

import "time"

// User represents a system user with selective TypeScript exposure.
type User struct {
    ID          int       `json:"id"`                // → id: number;
    Name        string    `json:"name"`              // → name: string;
    Email       string    `json:"email"`             // → email: string;
    Password    string    `json:"-"`                 // **Excluded** from .d.ts
    InternalKey string    `tsgo:"-"`                 // **Excluded** from .d.ts only
    CreatedAt   time.Time `json:"created_at"`        // → created_at: Date;
}

```

Running `tsgo` (or `go run ./cmd/tsgo`) on this package produces:

```typescript
export interface User {
    id: number;
    name: string;
    email: string;
    created_at: Date;
}

```

Notice that both `Password` and `InternalKey` are absent from the generated interface.

## Advanced Tag Combinations

You can combine tags to fine-tune behavior across JSON serialization and TypeScript generation.

### Keeping JSON but Hiding TypeScript

Use both tags when you want a field included in JSON payloads but omitted from type declarations:

```go
type Session struct {
    Token     string `json:"token" tsgo:"-"`  // In JSON, hidden from .d.ts
    ExpiresAt int64  `json:"expires_at"`
}

```

### Renaming While Preserving Other Fields

If you need to rename a field for TypeScript while excluding others, provide the desired name in the primary tag:

```go
type Event struct {
    RawData     []byte `tsgo:"-"`                // Completely hidden
    Timestamp   int64  `json:"eventTime"`        // → eventTime: number;
}

```

## Implementation Details in the Source Code

The exclusion logic resides in [`internal/transformers/tstransforms/typeeraser.go`](https://github.com/microsoft/typescript-go/blob/main/internal/transformers/tstransforms/typeeraser.go), which walks the Go AST and determines which members to preserve for the declaration file. The code checks struct tags for the omission marker `-` and filters accordingly.

Additional relevant files in the generation pipeline include:

- [`cmd/tsgo/main.go`](https://github.com/microsoft/typescript-go/blob/main/cmd/tsgo/main.go): Entry point that initiates the transformation pipeline
- [`internal/tsoptions/parsedcommandline.go`](https://github.com/microsoft/typescript-go/blob/main/internal/tsoptions/parsedcommandline.go): Handles the `--outputDts` flag that specifies where to write the [`.d.ts`](https://github.com/microsoft/typescript-go/blob/main/.d.ts) file
- [`internal/transformers/utilities.go`](https://github.com/microsoft/typescript-go/blob/main/internal/transformers/utilities.go): Provides helper functions like `IsGeneratedIdentifier` used during emission

## Summary

- **Unexported fields** (lowercase) are automatically excluded from TypeScript generation
- **Add `json:"-"`** to exclude a field from both JSON and TypeScript output
- **Add `tsgo:"-"`** to exclude a field only from TypeScript declarations while preserving JSON behavior
- **Combine tags** (`json:"name" tsgo:"-"`) to include data in JSON payloads but hide types from consumers
- The logic is implemented in [`internal/transformers/tstransforms/typeeraser.go`](https://github.com/microsoft/typescript-go/blob/main/internal/transformers/tstransforms/typeeraser.go) following Go's JSON encoding conventions

## Frequently Asked Questions

### Can I exclude a field from TypeScript but include it in JSON output?

Yes. Use the `tsgo:"-"` tag without a `json:"-"` tag. This hides the field from the generated [`.d.ts`](https://github.com/microsoft/typescript-go/blob/main/.d.ts) file while allowing standard JSON marshaling to include the field in API responses.

### Why does `json:"-"` affect TypeScript generation?

The `tsgo` generator reuses Go's JSON tagging logic to determine external field names. When the JSON tag is exactly `-`, the field is considered ignored for any external representation, so `tsgo` follows that convention for its own output as implemented in [`internal/transformers/tstransforms/typeeraser.go`](https://github.com/microsoft/typescript-go/blob/main/internal/transformers/tstransforms/typeeraser.go).

### Do I need to use both `json:"-"` and `tsgo:"-"` tags?

No. Either tag will exclude the field from TypeScript declarations. Use `json:"-"` when you want to suppress both JSON serialization and TypeScript generation. Use `tsgo:"-"` when you need the field in JSON but hidden from TypeScript consumers.

### How do I exclude multiple fields from the same struct?

Apply the exclusion tag to each field individually. There is no struct-level exclusion mechanism; you must tag each field you want to hide with either `json:"-"` or `tsgo:"-"`.