KorHosik
KorHosik

Reputation: 1267

Using a JS object to configure a class property type in TypeScript

Let's say I have an object of factories like this one:

const factories = {
  foo: () => 'some string',
  bar: () => 123,
};

I would like to use this object to type a class property. The goal for this class is to have a property with the same keys than above, but with the return type of the factories instead of the factories themselves:

class MyClass {
    myItems: ???; // What type here to have the below working?
}

const instance = new MyClass();
instance.myItems.foo; // Should be a string, not a function
instance.myItems.bar; // Should be a number, not a function

In short, I don't want that:

class MyClass {
    myItems: typeof factories;
}

But something like the below:

class MyClass {
    myItems: Record<keyof typeof factories, ReturnType<typeof factories>>;
}

But of course, the above does not work, with this error:

TS2344: Type '{ foo: () => string; bar: () => number; }' does not satisfy the constraint '(...args: any) => any'.   Type '{ foo: () => string; bar: () => number; }' provides no match for the signature '(...args: any): any'.

Do you have any help with that?

Thanks in advance!

Upvotes: 0

Views: 41

Answers (1)

Andrei Tătar
Andrei Tătar

Reputation: 8295

Here's a way you could do it:

https://www.typescriptlang.org/play?#code/MYewdgzgLgBAZgQ2FEAnAlgUwjAvDAbwCgZ4QQAuGACgEo8A+GAcghAFtMZoMwBzZgBoSMAEYJUVOoxgBGAEwBmYQF8A3ESJQAngAcuAMSQpU2gDwAVJvmm4mFjVr2HjabQDUEAGwCu2S9aEIgDaANIw6GAwANaY2iBwMBYAulQWYckwmAAeUJhgACY4RshuZpFwmKgwAKpMAPy1MFRgmABuVRrqmqCQsG3efhBUJSYeg-46+gnwrhjYgcSkcORUzHnQQiLiknJKqhpAA

const factories = {
  foo: () => 'some string',
  bar: () => 123,
};

type Factory<T> = () => T;

type FactoryValues<T> = {
  [K in keyof T]: T[K] extends Factory<infer U> ? U : never;
};

const values: FactoryValues<typeof factories> = {
  foo: 'test',
  bar: 123,
};

Upvotes: 1

Related Questions