Dusan Jovanov
Dusan Jovanov

Reputation: 567

Typescript Class where property names are unknown in advance

This is what I've tried

type SpecificType ={a:number; b:string};

type SomeInterface { 
  [key: string]: SpecificType
}  
class SomeClass implements SomeInterface {
  field1: {
   a: 1,
   b: ""  
 }
}

The problem is I get this error: Index signature is missing in type 'SomeClass'

It goes away if I put [key:string]: SpecificType in SomeClass, but I want to avoid that.

Also, TS doesn't recognize the type of fields in SomeClass.

Is there a solution for this ?

Upvotes: 1

Views: 321

Answers (3)

Andrey Markeev
Andrey Markeev

Reputation: 1404

It is actually possible to do via declaration merging. Just name the interface same as class.

type SpecificType = {a:number; b:string};

interface SomeClass { 
  [key: string]: SpecificType
}
 
class SomeClass {
  field1 = {
   a: 1,
   b: ""  
 }
}

If you have multiple classes, then use it like this:

type SpecificType = {a:number; b:string};
type SomeInterface = {
  [key: string]: SpecificType
};

interface SomeClass extends SomeInterface { }
class SomeClass {
  field1 = {
   a: 1,
   b: ""  
 }
}

TS Playground

Upvotes: 3

Dani
Dani

Reputation: 913

type SpecificType = { a: number; b: string };

abstract class SomeAbstractClass {
  [key: string]: SpecificType;

}
class SomeClass extends SomeAbstractClass {
  fields1 = {
    a: 1,
    b: "2"
  }
}

Upvotes: 3

Terry
Terry

Reputation: 66123

You can use generic types to do what you want: however, this is under the condition that when implementing SomeInterface you already know what member(s) of the class should implement that interface. Otherwise it is a chicken-and-egg problem and your original approach will be the only solution.

type SpecificType = { a:number; b:string };

type SomeInterface<T extends string> = { 
  [key in T]: SpecificType
}

class SomeClass implements SomeInterface<'field1'> {
  field1 = {
    a: 1,
    b: ""
 }
}

See it on TypeScript playground.

Upvotes: 1

Related Questions