TypeScript: Quick fix for 'unions can't be used in index signatures, use a mapped object type instead'
The following code:
type K = "foo" | "bar";
interface SomeType {
[prop: K]: any;
}
Gives this error message:
An index signature parameter type cannot be a union type. Consider using a mapped object type instead.
Nobody knows what mapped object types are, so let’s give them a quick fix that
- Switches the index signature to a mapped type
- Moves other members to a separate object type that gets combined with an intersection type
- Changes the containing object type to a type alias if the containing object type is an interface
- Intersects with all the
extendsclauses if the containing object type is an interface and has anyextendsclauses
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 291
- Comments: 37 (4 by maintainers)
You can do this:
Though
Barhas no index signature (i.e., you can’t then do(obj as Bar)[value as Foo]).Edit: Though if you could make the caveat a non-issue, I’d be eternally grateful!
Just curious why
typeworks, butinterfacedoesn’t. Can someone explain, please? What’s the reason for such a limitation (or a feature?) ofinterface.Use
Recordinstead!@maicWorkGithub here you go:
its even better when using Partial
To add one more example of this using a class…
No words, just meme: https://media1.tenor.com/images/23d9d746fc87b3a93298af43dae21f6a/tenor.gif
😃
Why exactly can’t an index signature use an enum type? The mapped type almost does what I want, but then TypeScript expects every string from the enum to exist as a defined key. I don’t actually want to assert that every key exists, more that if any keys do exist, they must live in the enum.
For example for the type:
This should satisfy:
While I could just set the other keys undefined for a mapped type, I prefer to make the keys optional, but if they’re present, the value cannot be undefined. If I make the mapped type values optional the code works but the types are less strong.
This was an amazing auto-fix to discover. Thank you for implementing it! 😃
“Partial” can be used on Records too:
I find myself unwittingly visiting this GitHub page every month or so.
My latest one is a real simple one:
I can scroll up and figure out a workaround, but just wanted to provide feedback that this issue happens frequently in day to day work in slightly different scenarios.
Thanks! Useful when you need to define a type that partially matches a dictionary
For typescript 3.5, it seems like I have to do this:
Is this the best way to do this?
@mvasin FWIW, this appears to achieve the same result, but I agree entirely that it should be a feature of interfaces just as it is on types.
what should we do if containing object type is an class?
I can only imagine that it is an interface
so what should follow code do after quickfix?
@b4dnewz fair enough,
Perhaps a simpler option you might be able to use is:
That’s about the closest you’ll get without too much duplication
@b4dnewz, if you only want 1 property, why not do it like this?
@ThaJay We won’t backport this feature, try setting up a newer version.