-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Index signature parameter type should allow for enums #2491
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: