2

We can declare index signature to force the properties of object to be of specific type such as below

const LOOKUP: {
  [key: string]: { name: string, age: number };
} = {
  isaac: { name: 'isaac', age: 20 },
  whatever: {name: 'whatever', age: 17}
};

However, I would like to restrict the possible values that goes as key, so below is my attempt

Attempt 1

type PossibleName = 'isaac' | 'john';

const LOOKUP: {
  [key: PossibleName]: { name: string, age: number };
} = {
  isaac: { name: 'isaac', age: 20 },
  whatever: {name: 'whatever', age: 17}
};

The attempt above hitting error below

An index signature parameter type cannot be a literal type or generic type. Consider using a mapped object type instead.

Attempt 2

type PossibleName = 'isaac' | 'john';

const LOOKUP: {
  [key in PossibleName]: { name: string, age: number };
} = {
  isaac: { name: 'isaac', age: 20 },
};

And attempt 2 is hitting error below

Property 'john' is missing in type '{ isaac: { name: string; age: number; }; }' but required in type '{ isaac: { name: string; age: number; }; john: { name: string; age: number; }; }'

I can solve it by making the key optional such as below

type PossibleName = 'isaac' | 'john';

const LOOKUP: {
  [key in PossibleName]?: { name: string, age: number };
} = {
  isaac: undefined,
};

It does allow to not declare john, but at the same time allowing value undefined for both isaac & john, which is not what I wanted.

My goal is that if I defined isaac, or john, the value should not be accepting undefined, but has to be of type { name: string, age: number}, wondering if that's possible?

9
  • 1
    "which is not what I wanted" So what do you want? Commented Sep 27, 2021 at 9:10
  • @FelixKling: My idea is that, if I defined Isaac, or john, the value should not be accepting undefined, but has to be of type { name: string, age: number}, wondering if that's possible? Commented Sep 27, 2021 at 9:15
  • From a practical runtime perspective, there is no difference between {} and john: undefined). Making something optional is the same as allowing its value to be undefined. Commented Sep 27, 2021 at 9:17
  • @FelixKling: agreed, however from code maintainability wise, i would like to throw error to developer if they ever assign undefined to the props, as undefined is a valid value. Exactly why i felt [key in PossibleName]? sounds weird coz I don't really wanna make it optional, but to restrict the possible values Commented Sep 27, 2021 at 9:19
  • 1
    So what you want is something like {john: Person} | {isaac: Person}? Or {john: Person} | {isaac: Person} | {john: Person, isaac: Person}? Commented Sep 27, 2021 at 9:23

1 Answer 1

1
type PossibleName = 'isaac' | 'john';
type Person = { name: string }
type MyType = {
  [K in PossibleName]: { [k in K]: Person }
}[PossibleName] | { [K in PossibleName]: Person }

Not pretty, just find a way to abuse TS engine. This will yield {john: Person} | {isaac: Person}| {isaac: Person; john: Person}

Playground

Sign up to request clarification or add additional context in comments.

2 Comments

It will still be possible to pass undefined values though typescriptlang.org/play?#code/…
That’s unexpected 🤔 I don’t understand what happened.

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.