0

I'm using a library that has a following class:

class ObservableObject<T> {
    constructor(value: T);
    get(name: keyof T);
    set(name: keyof T, value): void;
}

// example code
interface Dog { name: string; age: number }
let observableDog = new ObservableObject<dog>({ name: "Fifi", age: 1 });

When an ObservableObject is created all fields from source object are copied into it.

  1. Is it possible to merge ObservableObject with generic type T so I can access members directly without need to call get function ?

     // I have to do this
     let name = observableDog.get("name");
     // I want this
     let name = observableDog.name;
    
  2. Can typescript somehow figure out type of a field based on keyof operator ?

     // this should be an error because dog.name is a string
     observableDog.set("name", 0);
    

1 Answers1

0

I feel dirty, but you can do this with a class expression !

type ObservableObject<T> = {
  [S in keyof T]: T[S]
}
interface IObservableObject {
  new <T extends object>(a: T): ObservableObject<T>;
  new <T extends object>(a: T): ObservableObject<T>; // see https://github.com/microsoft/TypeScript/issues/50050
}

const ObservableObject: IObservableObject = (class <T extends object> {
  constructor(values: T) {
    Object.entries(values).forEach(([k, v]) => {
      (this as any)[k] = v;
    })
  }
})

let observableDog = new ObservableObject({ name: "Fifi", age: 23 });

observableDog.name // string
observableDog.age. // number

Playground

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
  • Woah? Double constructors? I thought this was a typo but then when I removed one of them, I got errors... Why's this? – kelsny Oct 05 '22 at 22:25
  • @caTS yeah I opened another question about this : https://stackoverflow.com/questions/73966918/generic-class-expression-broken-if-duplicate-constructor-is-removed – Matthieu Riegler Oct 05 '22 at 22:29