-
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
Using const string enum as object key produces an indexed type #16687
Comments
This should also work for numeric enums. |
Is this the same error? function make<Name extends string, Value>(name: Name, value: Value): Record<Name, Value> {
return {
[name]: value,
};
} Gives:
|
@simonbuchan Not really. @Kovensky wants the keys of strings enums to be statically known for use in computed properties. You want one unknown member of an unknown set of keys to be create a type with computed name in it. Something like Unfortunately, Typescript doesn't have a type like this, though, so instead the type inferred for the object literal has a string indexer, which is not assignable to a mapped type, even though both have an unknown set of allowed properties. You'll have to read the PRs for mapped types, but I think the reason is that a string indexer will always have an unknown set of properties, but the mapped type, when instantiated, will have a particular set of properties. For example: make('hi', 'there'): Record<'hi', string> And |
@sandersn I think I get it reflecting on this a bit: function make<Name extends literal string, Value>(name: Name, value: Value): { [name: Name]: Value };
make("foo", "bar"); // { foo: string } - though I would like { foo: "bar" }, that's another issue
["foo", "bar"].map(name => make(name, name)); // either error on make "'string' is not assignable to 'literal string' or Array<{ [name: string]: string }> as before?
function zipMake<Names extends string, Values>(names: Names[], values, Values[]) {
return names.map((name, i) => make(name, values[i])); // "'Names' is not assignable to 'literal string'"
}
function zipMake<Names extends literal string, Values>(names: Names[], values, Values[]); // Either error or can only be called with 0 or 1-length literal array of `names` (or matching constrained type)? This arose when I was playing around with a toy version of type WithCounterEnhancer = <ExternalProps>(
wrappedComponent: React.ComponentType<ExternalProps & { counter: number, setCounter(value: number }>,
): React.ComponentType<ExternalProps>; I could get it to typecheck pretty well externally with |
@simonbuchan Do you mind creating a separate issue for this with your example code and discussion? This feels like it is generating discussion distinct from that based on the original example. I'll see if I can answer your questions there. |
another interesting use case described in #17784 class Component<S> {
state: S;
setState(partialState: Partial<S>) { }
onFiledChanged = (filedName: keyof S) => (value) => {
this.setState({ [filedName]: value });
}
render() {
return <form>
<input onChange={ this.onFiledChanged('foo') } />
<input onChange={ this.onFiledChanged('bar') } />
</form>
}
} |
#15473 should be to fix this. |
Note that this does not cover the generic case, i.e. function f<K extends string>(k: K) {
return { [k]: 0 } ; // type is { [x:string]: number}
} for these cases we recommend casting to type Unionize<T> = {[P in keyof T]: {[Q in P]: T[P]}}[keyof T];
function f<K extends string>(k: K) {
return { [k]: 0 } as Unionize<{[P in K]: number}>;
} |
Edit 3: OK, tried on nightlies, and it looks like with #18317 |
I would like this feature to work too, but I have a couple of issues
export const enum StepNames {
one = 'one',
two = 'two',
final = 'final'
}
export type Step = {[key in StepNames]: {header: string}}; When I try to use it like: const oneStep: Step = { 'one': { header: 'First' } }; I get this compile error:
const enum Test {
A = 'a',
B = 'b'
}
type TestMap<T> = {[key in keyof T]: string}
const x: TestMap<Test> = {
['a']: 'string',
['b']: 'another string'
}
// Error: TS2322: Type '{ ['a']: string; ['b']: string; }' is not assignable to type 'Test'. Is there any way to get around this problem? |
@SLaks Thanks. Sorry for the basic questions. |
TypeScript Version: nightly (2.5.0-dev.20170621)
Code
Expected behavior:
Keys from a string enum to be usable as static key names, similar to how constant strings are usable in computed key position. This probably should work even with non-
const
enums.Actual behavior:
Not usable without a (potentially incorrect?) type assertion.
The text was updated successfully, but these errors were encountered: