0

Is it possible to model a simple recursive relationship like the following? I want to restrict the types of values added to a generic container to primitives or other containers. Since interfaces can't extend from types, and types cannot reference themselves, it's not immediately clear whether this is possible:

  type Primitive = string | boolean | number | null;
  type Value = Primitive | MyMap<Value>;  // <-- error here


  interface MyMap<T extends Value> {
    get(k: string): T;
    set(k: string, v: T): void;
  }
Chris Colbert
  • 868
  • 7
  • 12
  • Note that this question is similar to [an earlier one](https://stackoverflow.com/questions/36966444/how-to-create-a-circularly-referenced-type-in-typescript), although the specifics are possibly different enough to warrant keeping this as a separate question. Not sure. – jcalz Jul 18 '17 at 16:10

1 Answers1

2

Types can reference themselves (see the spec), but there are definitely pitfalls. For your specific case I would probably do something like:

type Primitive = string | boolean | number | null;

type Value = Primitive | MyMap; 

interface MyMap {
  get(k: string): Value;
  set(k: string, v: Value): void;
}

without the generic to confuse things.


Update 1

@Chris Colbert said:

The generic is important though, because I want to be able to do things like this: let m1: MyMap<string>; let m2: MyMap<MyMap<number>>; and so on.

Okay, try:

type Primitive = string | boolean | number | null;

type Value = Primitive | {
  get(k: string): Value;
  set(k: string, v: Value): void;
}

interface MyMap<T extends Value> {
  get(k: string): T;
  set(k: string, v: T): void;
}

declare let m1: MyMap<string>; 
declare let m2: MyMap<MyMap<number>>;
jcalz
  • 264,269
  • 27
  • 359
  • 360
  • The generic is important though, because I want to be able to do things like this: ``` let m1: MyMap; let m2: MyMap>; ``` and so on. – Chris Colbert Jul 18 '17 at 16:18
  • Thanks. It's interesting that that works, but not my original example. Unfortunately, this is a minimal example, the real code has many more methods as well as other collection types, so it would be prohibitive to scale this pattern at that level. – Chris Colbert Jul 18 '17 at 16:33
  • Oh well, sorry. Is there anything about my answer which needs changing before you'd accept it? – jcalz Jul 18 '17 at 16:40