-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Index signature parameter type should allow for enums #2491
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
+1, this is a great way for type-safe dictionaries. |
+1 If the TS team embraces 'set types' #3105, this would work too:
|
Would likely require at the minimum in the compiler something like:
|
This does seem very useful. Going back to the original example, we had some questions about the intended semantics. Given some types: enum Color { red, green, blue }
enum Size { small, medium, large }
interface Alpha {
[c: Color]: string;
}
interface Beta {
[c: Size]: string;
}
interface Gamma {
[c: number]: string;
}
interface Delta {
[c: Color]: string;
[c: Size]: string;
} Obvious things:
Non-obvious things:
|
(a)
No (b)
Yes (unfortunately), follow isTypeAssignableTo()
I'd be happy if (c) changed eventually so that const enums only accept constants or types within their range of values. |
While the use cases make sense, we didn't think this provided enough value to justify its added complexity. |
Would be great to elaborate on |
There's not a huge amount to add -- we understand the use cases, we understand the value proposition, and we understand the additional complexity. Given a finite complexity 'budget', we didn't think this was worthwhile compared to other things we could do instead. |
So it's a resource constraint rather than technical complexity? |
@RyanCavanaugh Don't get it, #1863 #2012 are still open so there's a type indexer |
More elaborate example:
Supporting symbols means your complexity Now the compiler has something like:
Just don't see what |
Should be possible now with MappedTypes. So the example in the OP can be: export type UserInterfaceColors = {
[P in UserInterfaceElement]: ColorInfo;
} |
@mhegazy: it seems like it might be a little trickier than that in practice? export enum MyEnum {
First = 0,
Second = 1,
}
export type EnumMap = {
[P in MyEnum]: string;
}
// [ts] Type '{ [x: number]: string; }' is not assignable to type 'EnumMap'.
// Property '0' is missing in type '{ [x: number]: string; }'.
const doesntWork: EnumMap = {
[MyEnum.First]: "first",
[MyEnum.Second]: "second",
};
const works: EnumMap = {
0: "first",
1: "second",
};
// but then this is allowed, should it be?
works["foo"] = "bar";
// but then:
// [ts] Property 'foo' does not exist on type 'EnumMap'.
type test = typeof works["foo"] |
You can use any type as the key for class DictValues<V> {
[key: string]: V;
[key: number]: V;
}
interface ToStringer {
toString(): string;
}
class Dict<K extends ToStringer, V> {
private _values: DictValues<V> = Object.create(null);
get(key: K): V {
return this._values[key.toString()];
}
set(key: K, value: V): void {
this._values[key.toString()] = value;
}
has(key: K): boolean {
return this._values.hasOwnProperty(key.toString());
}
values(): DictValues<V> {
return this._values;
}
} |
@mhegazy: I get export type UserInterfaceColors = {
[P in UserInterfaceElement]: ColorInfo;
} Coupled with the bits @jkillian mentioned makes me think this should be reopened (or at least the |
This was broken by #12425. would you mind logging a new issue to allow numeric literals as constraints of mapped types? |
Hi, I would also benefit from being able to use a declared type as index, so that I can restrict which kind of indexes are being used. For example:
What I try to achieve is that the validation will be a dictionary and has the key 'email' and the value type of string, and a required validation. A text field would only have Required validation. The Javascript object looks like this:
Right now I can only allow all possible validations but I can't restrict the set of validations per field type. This is because of the index must to be string or number restriction. If it would be possible to define a dictionary like this:
Any thoughts? |
This seems to be quite frequent pattern, would be nice to support it.
|
@apetrushin you can use "in" for this
|
Thanks, but it's still allows to do |
Have a look at my post just above. That would be an awesome addition. Right now we can only defined the index of a dictionary to be of a string but not restrict to a list of string types. |
This appears broken again as of TS 2.4 (2.x?) enum Things { ONE, TWO }
// Error: Type 'Things' is not assignable to type 'string'.
type ThingMap = {[TKey in Things]: boolean}; |
It appears this is a known regression with a fix on the roadmap: #13042 |
@nevir I am using enum Things { ONE = 'one', TWO = 'two' } Should be that the default behavior? or should be just doing the enum without any mapping? |
Typescript requires that enums have number value types (hopefully soon, this will also include string value types).
Attempting to use an enum as a key type for a hash results in this error: "Index signature parameter type much be 'string' or 'number' ".-- An enum is actually a number type.-- This shouldn't be an error.
Enums are a convenient way of defining the domain of number and string value types, in cases such as
The text was updated successfully, but these errors were encountered: