2

I have the following type - export type Sizes = 'small' | 'medium' | 'big' and I want to use this type as keys for an object I'm creating:

type SizeInformation = {
  [key in Sizes]: string;
}

However, the desired functionality here is that this type (and therefore the object that will be created based on it) doesn't necessarily need to have all keys named, or none at all, but if a key goes into the object, it should be of type Sizes.

As such, an empty object would be valid, an object with just the key medium would also be valid, but if an object has the keys medium and sea, it is not valid, as, again, all keys need to be of type Sizes.

I've played around with Partial but to no avail.

How can I achieve that? Thank you.

3
  • You can make a type to generate a union of all the possible types but obviously that won't scale very well :) Commented Mar 6, 2022 at 14:08
  • @DanielIvory : Checkout the solution which I have provided. If it works, you can accept the answer to close the discussion Commented Mar 6, 2022 at 14:24
  • When you say “but to no avail”, can you explain exactly what you mean? Partial should work here. Commented Mar 6, 2022 at 22:54

2 Answers 2

2

It is very simple. You can use two Utility Types, Partial and Record, together.

type Sizes = 'small' | 'medium' | 'big'

// Following code will create type that can accept keys which are of type Sizes and which will be optional
type SizeInformation = Partial<Record<Sizes, string>>;


const obj : SizeInformation = {
    big: 'big',
    medium: 'medium',
    small:'small'
}

For reference https://www.typescriptlang.org/docs/handbook/utility-types.html

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

2 Comments

In the question it is noted that they do not want the behavior of Partial because it allows undefined.
He said he played with Partial but did not get expected behavior. As per description, he want type with the keys of type Sizes and object can we empty or one can provide value to any key.. As per this description above solution works
1

You should leave your index signature the same. Index signatures are stating for what the shape of properties/values would be if they were enumerable (or actually assigned). Therefore, you should always have your index signatures as non-undefined. If you want strict index signature access where you need to handle for a key not being in the object, then you should enable the noUncheckedIndexedAccess config property because it will force you to handle for the undefined case when using index signatures. See the reference on noUncheckedIndexedAccess

2 Comments

I see, is this a limitation of TS? Because it's really, really bad when I have to tell whoever's using my code that they need to have X setting enabled in their tsconfig or so.
@DanielIvory This is not exactly a limitation of TS. It is more of a problem that the TS team realized later on and adding the noUncheckedIndexedAccess config property was more of a bandage to allow teams to move to safer code. As I described in my answer, you can still just make the index signature include undefined by using optional notation. However, you should go with best practice and not include undefined in the signature and instead enable noUncheckedIndexedAccess to whoever is actually using your code to decide if they want safe indexing.

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.