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
The elements included in the array by ...keyof(X) would be exactly every element considered by keyof X in a type declaration; not necessarily in any particular order.
Discussion
Encasing the ...keyof(*) expression in brackets (as may be expected from a spread operation meant to provide an array) would make it syntactically ambiguous and prevent someone from having a keyof function. As far as I know, spread is not used outside of brackets and braces aside from in parameters and left side of assignment, where it would be nonsensical anyway, so at least for now this is probably not syntactically ambiguous with ES.
This brings the keyof() expression into code space instead of type declaration space, but I couldn't think of a cleaner alternative.
There's an argument that it should generate an object with the keys being keys and the types being values; however, it is an enormous can of worms to define which objects should be used to reify the type declarations, or to which extent that should even occur or be allowed. I'm not proposing full introspection, just a way to bridge the gap and carry some remnant of interfaces and types into the generated JavaScript.
Yes, true, although I don't quite see how string enums (proposed as the answer in that issue) would work to solve any problem this would solve unless we were to get automatic string enums with the member names of every interface/type somehow.
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
I feel that this could bring a unique capability that string enums could not that may have been overlooked. Instead of having const animalProperties = ['weight', 'length', 'height', 'name']; have a type of string[], it would instead have a type of (keyof IAnimal)[] and allow index access with type number | string. It would be very powerful for a Record type or interface where all fields are the same type. Here is an example:
interface GroupDescription {
name: string;
description: string;
}
const GroupKeysWorkaround: Group[] = ['red', 'blue', 'green'];
type Group = 'red' | 'blue' | 'green';
type Groups = { [K in Group]: GroupDescription };
enum GroupKeysEnum { red = 'red', blue = 'blue', green = 'green' };
type GroupsEnum = { [K in GroupKeysEnum]: GroupDescription }
// DRY issue with having to mantain two seperate lists of groups
function initGroupsWorkaround(groups: Groups) {
for(const group of GroupKeysWorkaround) {
const name = groups[group].name;
processName(name); //Generically Process property
}
}
// Ugly hack casting any twice and filtering out bad enum values
function initGroupsEnum(groups: GroupsEnum) {
for(const group of Object.keys(GroupKeysEnum)) {
if(Number(group) !== NaN) return; // Filter out numbers
const groupKey: GroupKeysEnum = <any>group;
const name: string = (<any>groups)[groupKey].name;
processName(name); //Generically Process property
}
}
// Prefered method
function initGroups(groups: Groups) {
for(const group of ...Group) { // group would be type Group or 'red' | 'blue' | 'green'
const name = groups[group].name;
processName(name); //Generically Process property
}
}
// Another prefered method
function initGroupsAlt(groups: Groups) {
for(const group of ...keyof(Groups)) { // group would be type Group or 'red' | 'blue' | 'green'
const name = groups[group].name;
processName(name); //Generically Process property
}
}
function processName(name: string) { }
Update - I noticed I don't need ...keyof but instead directly use the spread operator on the union type. Both seem okay to me, but having the ... directly on the union string literal seems more straightforward.
I think const animalProperties = keyof(IAnimal); should actually generate 'weight' | 'length' | 'height' | 'name' and ...animalProperties should generate an array ['weight', 'length', 'height', 'name'] of type ('weight' | 'length' | 'height' | 'name')[]. This way you can compose however you prefer.
Activity
mhegazy commentedon May 11, 2017
looks like a duplicate of #13542
JesperTreetop commentedon May 12, 2017
Yes, true, although I don't quite see how string enums (proposed as the answer in that issue) would work to solve any problem this would solve unless we were to get automatic string enums with the member names of every interface/type somehow.
mhegazy commentedon May 30, 2017
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
wizarrc commentedon Jul 10, 2017
Mohamed Hegazy (@mhegazy) Please reopen.
I feel that this could bring a unique capability that string enums could not that may have been overlooked. Instead of having
const animalProperties = ['weight', 'length', 'height', 'name'];have a type ofstring[], it would instead have a type of(keyof IAnimal)[]and allow index access with typenumber | string. It would be very powerful for aRecordtype or interface where all fields are the same type. Here is an example:Update - I noticed I don't need
...keyofbut instead directly use the spread operator on the union type. Both seem okay to me, but having the...directly on the union string literal seems more straightforward.wizarrc commentedon Jul 10, 2017
I think
const animalProperties = keyof(IAnimal);should actually generate'weight' | 'length' | 'height' | 'name'and...animalPropertiesshould generate an array['weight', 'length', 'height', 'name']of type('weight' | 'length' | 'height' | 'name')[]. This way you can compose however you prefer.