TypeScript: Excluding getter-only properties from type

Updated: January 8, 2024 By: Guest Contributor Post a comment

Introduction

In the realm of TypeScript, molding types to one’s precise requirements is akin to working the earth for a harvest. Just as a planter might choose to separate wheat from chaff, so might a TypeScript artisan desire to exclude getter-only properties from a type, refining the final construct to pure utility. In this tutorial, we traverse the methods to achieve just that, with finesse and forethought more fitting a scribe than a smith.

Understanding Getter-Only Properties

Getter-only properties in TypeScript serve as windows into the soul of an object, allowing one to glance upon its internal state without the liberty to alter its countenance. They embody a read-only contract, asserting that their charge is to reveal but never to receive. A TypeScript type housing such properties might resemble an old tome – insightful, but unyielding to the hand of change.

class MysticalValues {
  private secretValue: number = 42;

  public get secret() {
    return this.secretValue;
  }
}

Excluding Properties with Mapped Types

Mapped types in TypeScript are a cartographer’s tools for the terrain of types, sketching out new regions of possibilities. Donning this tool, one may exclude the unwieldy getter-only properties by mapping over an existing type and reconstructing it with precision and intent.

type Writeable = {
  [P in keyof T]-?: T[P] extends (...args: any[]) => any ? never : P
};

type MutableClassProperties = Writeable;

Utilizing Utility Types

TypeScript offers a wealth of utility types; vessels that carry one across the tumultuous seas of type manipulation. The built-in Exclude utility type is such a vessel by which one can filter out the getter-only properties, aligning the type to one’s aim with the precision of a master archer.

type KnownKeys = {
  [K in keyof T]: string extends K ? never : number extends K ? never : K
} extends {
  [_ in keyof T]: infer U
}
  ? U
  : never;

type ExcludedGetters = Pick<T, Exclude<KnownKeys, KnownKeys<{ [P in keyof T]: T[P] }>>;

type NoGetters = ExcludedGetters;

Advanced Exclusion Techniques

While utility types and mapped types are sturdy vessels and tools, the quest for excluding getters may sometimes require one to delve even deeper, forging a path through more arcane aspects of TypeScript’s type machinations. Conditional types paired with infer declarations can act as a divining rod, sourcing the spring of properties to be excluded with near-spectral insight.

type NonFunctionPropertyNames = {
  [K in keyof T]: T[K] extends Function ? never : K
}[keyof T];

type NonFunctionProperties = Pick<T, NonFunctionPropertyNames>;

type StrictlyKnown = NonFunctionProperties;

Summary

As we gather our parchments and quills, we reflect upon the lessons transcribed. The act of excluding getter-only properties from a type in TypeScript remains a curious arte of codery, respecting the access intended by the architect of the object while shaping the type to the tailor’s own pattern. May this treatise serve as your guide, clairvoyant and clear, as you too seek to enforce the distinction between the seen and the altered in the annals of your TypeScript dominions.