Repository navigation
allow string literals (unions of string literals?) as a type of an indexer #7656
Description
Activity
I also encountered this and considered opening an issue, though having a string literal union as a key type would have very similar semantics to:
type Keyed<a> = { this?: a; that?: a }
Which would appear a bit more verbose and require more typing though.
However, the indexer approach does have the advantage that it allows aliasing the key type (the string literal union) separately, e.g:
type RequestMethod = "GET" | "SET" | "PUT" | "UPDATE" | "DELETE"; type HandlerObject = { [key: RequestMethod]: (requestObject: RequestObject) => boolean; };
I think that based on the usefulness of this particular pattern it should definitely be considered to become valid syntax.
Also, the same pattern may also prove useful when the numeric literal type is introduced:
type ValidNumericKey = 1 | 2 | 4 | 8 | 16; type ValueObject = { [key: ValidNumericKey]: SomeObject };
zpdDG4gta8XKpMCd commented
on Mar 23, 2016 AuthorMore actionsit's not an equivalent, my Keyed can take from 0 through 1 to 2 values,
whereas yours always needs exactly 2completely different semantics
On Mar 23, 2016 12:47 PM, "malibuzios" notifications@github.com wrote:I also encountered this and considered opening an issue, though having a
string literal union as a key type would have very similar semantics to:type Keyed = { 'this': a; 'that': a }
Which would appear a bit more verbose and require more typing though.
However, the indexer approach does have the advantage that it allows
aliasing the key type (the string literal union) separately, e.g:type RequestMethod = "GET" | "SET" | "PUT" | "UPDATE" | "DELETE";type handlers = { [key: RequestMethod]: (requestObject: RequestObject) => boolean; };
I think that based on the usefulness of this particular pattern it should
definitely be considered to become valid syntax.Also, the same pattern may also prove useful when the numeric literal type
#7480 is introduced:type ValidNumericKey = 1 | 2 | 4 | 8 | 16;type values = { [key: ValidNumericKey]: SomeObject };
—
You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#7656 (comment)I was just about to fix it when you replied. I changed it to make all properties optional, though it may still not have the same exact semantics, but the difference may be subtle. Can you think of any other differences?
Well there's one difference (that's isn't really about semantics) that the interface style notation, based on current behavior, would allow using the dot (
.) operator, but the indexer wouldn't:type Keyed1<a> = { this?: a; that?: a } type Keyed2<a> = { [key: 'this' | 'that']: a; } let x: Keyed1<number> = {}; let y: Keyed2<number> = {}; x['that'] = 34; // OK x.that = 34; // OK y['that'] = 34 // OK y.that = 34 // Error
However that behavior could be changed in case the key is a string literal, I guess, perhaps, maybe?
- addedSuggestionAn idea for TypeScriptAn idea for TypeScriptNeeds More InfoThe issue still hasn't been fully clarifiedThe issue still hasn't been fully clarified
on Mar 23, 2016 RyanCavanaugh commented
on Mar 23, 2016 MemberMore actionsCan you explain what you expect this to do?
Is it equivalent to this?
type Keyed<a> = { 'this': a } | { 'that': a };
Ryan Cavanaugh (@RyanCavanaugh)
I believe (though of course I may be subtly wrong) the idea is that the string literal union constrains what keys can be used to a finite set, in this case
{"this", "that"}. For simplicity let's assumeais anumbertype Keyed = { [key: 'this' | 'that']: number; }
I believe the possible values for
let x: Keyedare:x = {}; // or x = { 'this': ...some number... } // or x = { 'that': ...some number... } //or x = { 'this': ...some number..., 'that': ...some number... }
RyanCavanaugh commented
on Mar 23, 2016 MemberMore actionsSo
{ 'this': 4, 'something': 6 }would be invalid?Ryan Cavanaugh (@RyanCavanaugh)
Based on my understanding that would seem like the most natural interpretation of this combination of the indexer syntax and the concept of string literal union applied to the key.
It also seems like this may mean that unlike the semantics of an "normal" interface this would be a strict type, i.e. not assignable from a wider type (having additional properties)?
Ryan Cavanaugh (@RyanCavanaugh)
Or the fact it's still enclosed within the "brackets"
{}, representing an interface, means it's still extensible?zpdDG4gta8XKpMCd commented
on Mar 23, 2016 AuthorMore actionswhy? to limit the possible set of keys, prevent unexpected keys from
possibly being used
On Mar 23, 2016 1:23 PM, "Ryan Cavanaugh" notifications@github.com wrote:Can you explain what you expect this to do?
Is it equivalent to this?
type Keyed = { 'this': a } | { 'that': a };
—
You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#7656 (comment)Ryan Cavanaugh (@RyanCavanaugh)
I'm sort of rethinking this. Perhaps we need to separate the two different aspects of semantics here:
- What can be indexed into this - which based on the natural interpretation of literal types I believe should only include the strings "this", "that" and no more.
- What can be assigned to this - Is this a "strict" interface that only takes the 4 variations I listed, or does this behave like an all optional interface? which very unfortunately today is even assignable from anything - personally I feel this is one of those anomalies where I'm amazed still happens and nothing has really been done about (though to be fair it seems like a pull request was open at some point).
I think we have a bigger problem here: it seems like indexer key types are not even checked for conventional types like
stringornumber(there may be an open issue for this but I haven't searched yet):These two examples don't induce any errors whatsoever (tested on playground and 1.8.7):
type A = {[key: number]: any}; let a: A = {}; a["abcd"] = 1; // No error? let x = a["abcd"]; // No error?
type B = {[key: string]: any}; let b: B = {}; b[123] = 1; // No error? let y = b[123]; // No error?
- addedDuplicateAn existing issue was already createdAn existing issue was already created
on Mar 23, 2016 Aleksey-Bykov Ryan Cavanaugh (@RyanCavanaugh)
This comment in #7660 is a direct continuation of the discussion here, but applied to the more general issue of the how strictly should index signature keys be type-checked.
- locked and limited conversation to collaborators
on Jun 19, 2018