You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This needs more fleshing out. Currently number and string indexers have very different behavior; it's not at all obvious what the behavior of the "combined" key type would be. At a minimum we need to see what the desired behavior of this would be other than simply allowing its declaration to exist.
At least it would be very useful to have the ability to use string literal union type as an indexer. As people have already pointed out in #5185 (comment)
It is more limited than initial proposal, but added value will be tremendous.
Reacted by Mathieu Masy, Marcel Šebek, Nathan Liebrecht and Tomáš Hübelbauer
The problem with mapped types is that once you converted anything to type, you cannot use it as an interface, e.g.: no more implements for classes, and that's quite a bit trade-off.
I wonder if there are any ideological objections to allowing simple mapping syntax inside of interfaces.
typeAllWorks<T>={[KinkeyofT]: T[K];// ok}interfaceDoesNotWork<T>{[KinkeyofT]: T[K];// would be great for this syntax to work inside of interfaces}
While first one works as expected, second one gives the TS error:
[ts] A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
[ts] Member '[K in keyof' implicitly has an 'any' type.
[ts] Cannot find name 'keyof'.
Reacted by John Maillet, Kevin Upton and Robin Baum
I think what would be ideal is having generic types, but having the compiler validate the type when it is used. (for the key validation).
An example where a function returns:
{[key : T[K]] : T}
T being an object, and K being keyof T
Example Code:
A function which takes an array of objects, and returns an object map, with the each object mapped to the input key.
interfaceType{[key: string]: any;}/** * Function which maps an array to an object. * This will convert [{id, test}...] => {id: {id, test}...} * Useful for creating cache maps. * * @param {K} key * @param {T[]} objects * @returns {{[p: string]: T}} */exportfunctionmapArrayToObject<TextendsType,KextendskeyofT>(key: K,objects: T[]): {[key: T[K]]: T;// it should recognise that this is a variable type which depends on the input, and validate it on use.}{returnObject.assign({},
...objects.map(object=>({[object[key]]: object})));}
Then when they use the method:
This should work
interfaceTest{id: string;value: any;}consttestArray: Test[]=[];mapArrayToObject('id',testArray);// this should work because id is a string type and key accepts string.
This should fail
interfaceTest2{id: object;value: any;}consttest2Array: Test2[]=[];mapArrayToObject('id',test2Array);// this should fail because it recognises that `id` is an object. And you cannot have an `object` as a key.
Mohamed Hegazy (@mhegazy) Is there an issue tracking the is contraint suggestion in the OP? I am trying to write a propertyIsDefined function like this to help with #10976 (comment):
exportconstisDefined=<T>(val: T): val is NonNullable<T>=>val!==undefined&&val!==nullexportconstpropertyIsDefined=<Textendsobject,KextendskeyofT>(key: K)=>(val: T): val is T&{[kinK]: NonNullable<T[k]>}=>isDefined(val[key])
which works, but it is only type safe if K is a single string literal. If K is a union, this function is not type safe anymore, as it would mark all properties in K as non-null, instead of one of the properties in K. I would like to forbid passing in a union, K should be an exact element of keyof T, but extends allows to pass any subtype of keyof T.
Activity
DanielRosenwasser commentedon Feb 21, 2015
So for your example, I think what you're looking for is really the ability to index with a union type:
Which wasn't allowed when we first introduced union types, but for 1.5 you should have it through #1765.
danquirk commentedon Apr 3, 2015
This wasn't a change we made, so re-opening this although it's not clear how useful it is.
yjo commentedon Aug 6, 2015
+1, am wanting to do this now to write a type definition for Lodash's
_.mapKeysRyanCavanaugh commentedon Jan 4, 2016
This needs more fleshing out. Currently number and string indexers have very different behavior; it's not at all obvious what the behavior of the "combined" key type would be. At a minimum we need to see what the desired behavior of this would be other than simply allowing its declaration to exist.
aindlq commentedon Aug 3, 2016
At least it would be very useful to have the ability to use string literal union type as an indexer. As people have already pointed out in #5185 (comment)
It is more limited than initial proposal, but added value will be tremendous.
danielearwicker commentedon Sep 2, 2016
And now number literal union type as indexer!
jovdb commentedon Aug 4, 2017
I also would like to have indexer with generics support:
to represent:
weswigham commentedon Aug 25, 2017
The examples in this thread can be represented, today, with mapped types.
Is there still a feature request here?
c69 commentedon Mar 14, 2018
The problem with mapped types is that once you converted anything to type, you cannot use it as an interface, e.g.: no more
implementsfor classes, and that's quite a bit trade-off.I wonder if there are any ideological objections to allowing simple mapping syntax inside of interfaces.
While first one works as expected, second one gives the TS error:
kevupton commentedon Apr 17, 2018
I think what would be ideal is having generic types, but having the compiler validate the type when it is used. (for the key validation).
An example where a function returns:
Tbeing an object, andKbeingkeyof TExample Code:
A function which takes an array of objects, and returns an object map, with the each object mapped to the input key.
Then when they use the method:
This should work
This should fail
felixfbecker commentedon May 11, 2018
Mohamed Hegazy (@mhegazy) Is there an issue tracking the
iscontraint suggestion in the OP? I am trying to write apropertyIsDefinedfunction like this to help with #10976 (comment):which works, but it is only type safe if
Kis a single string literal. IfKis a union, this function is not type safe anymore, as it would mark all properties inKas non-null, instead of one of the properties inK. I would like to forbid passing in a union,Kshould be an exact element ofkeyof T, butextendsallows to pass any subtype ofkeyof T.weswigham commentedon May 12, 2018
Felix Becker (@felixbecker) you just wanna decompose any input unions before you map, eg
which should handle the input as union case like you'd like.
felixfbecker commentedon May 12, 2018
Wesley Wigham (@weswigham) wow, works like a charm! I would have never thought about that. How does it work? Shouldn't
K extends anyalways be true?RyanCavanaugh commentedon Jun 24, 2021
Discussion here has wandered quite a bit but the OP use case works now.