0

I have an object defined with string keys and number values:

class MyService {
  private static readonly MAPPING: { [ index: string ]: number } = {
    a: 16,
    b: 32,
  };
}

And I would like to have another object that only allows the values (numbers) defined in that mapping as keys



class MyService {
  private static readonly MAPPING: { [ index: string ]: number } = {
    a: 16,
    b: 32,
  } as const;
  public static states: { [ index in ?!? (Object.values(MyService.MAPPING)) ?!? ]: boolean } = {}; // <-- clearly this is wrong
}

So that: MyService.states[16] = true would be valid, but MyService.states[17] = true would not.

How can I accomplish this?

1 Answer 1

1

Since you are not allowed to define a type within a class, you will have to define the type using the constant object on the root level of the file and use it in your class.

const MAPPING = {
  a: 16,
  b: 32,
} as const;

type MAPPING_VALUE = typeof MAPPING[keyof typeof MAPPING];

class MyService {
  public static readonly MAPPING: { [index: string]: number } = MAPPING;
  public static states: {
    [index in MAPPING_VALUE]: boolean;
  } = {
    16: true,
    32: false,
  };
}
Sign up to request clarification or add additional context in comments.

4 Comments

For initialization, we can restrict access by union types, but for value access, we can't do that. In other words MyService.states[44] = true; will be also valid due to dynamic property search. For dot notation, we need a valid identifier, like this $16.
i've just tried it and it seems it's not like you described MyService.states[16] = true is valid according to ts, but typescript MyService.states[44]= true isn't.
Interesting.. Thank you. I still am getting used to the idea of having things like that defined outside of classes, that has always felt "wrong" to do.
in case you use a type that doesn't belong to your MAPPING values you will see (eg: 17): Element implicitly has an 'any' type because expression of type '17' can't be used to index type '{ 16: boolean; 32: boolean; }'. Property '17' does not exist on type '{ 16: boolean; 32: boolean; }'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.