-
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
No way to express hybrid types that are indexable for a subset of properties #15151
Comments
I've run into the same issue. With the type system as it stands, I'm unable to express the type of a UISchema from the react-jsonschema-form library. interface UiSchemaMap {
[propertyName: string]: UiSchema;
}
interface UiSchemaItemOptions {
addable?: boolean;
orderable?: boolean;
removable?: boolean;
}
interface UiSchema {
classNames?: string;
items?: UiSchemaMap;
'ui:disabled'?: boolean;
'ui:dirty'?: boolean;
'ui:field'?: string;
'ui:options'?: UiSchemaItemOptions;
'ui:order'?: string[];
'ui:readonly'?: boolean;
'ui:rootFieldId'?: string;
'ui:widget'?: string;
[other: string]: UiSchema | undefined; // This is failing to compile
} So far, I've found two possible workarounds, but they're both far from ideal. Let's use this minimal failing example: interface NotWorking {
name: string;
age: number;
[other: string]: NotWorking;
} One way to get it passing is to instead declare the type of the indexed type as interface Working {
name: string;
age: number;
[other: string]: any;
} The other way is to declare all the other types as union types and cast those. This also pains me to do. interface Working {
name: string | Working;
age: number | Working;
[other: string]: Working;
} It would be really great if indexed properties could have a consistent type that differed from the named and explicitly declared properties. |
An index signature adds a constraint on the type; since named properties are just a subset of what can be used to index into an object, they need to fit into the constraint defined by the index. use intersection types to achieve what you are looking for: type T = { a: number, b: string } & { [x: string]: boolean }; |
@mhegazy Have you tried what you are suggesting? It does not work. It is no different from combining the types as described above. Please adjust the labels accordingly, this is not a question, consider this a feature request or a bug. |
i did not try that to be frank. i was more thinking of using the type to access the properties.. e.g. declare const t: T;
t.a // number;
t["b"] // string
t["somother"] // boolean |
My particular case doesn't have much use for a type that can only be read. Honestly, it's a bit surprising that typescript doesn't realize that an impossible type is being made. I don't know all of the ramifications, but I think that this design decision should be reconsidered. Flow does it the other way (the map type is the fallback, not an intersection) and I do not know of any issues with that. |
Could the label on this be updated to "feature request" instead of "question" as @aaronjensen suggested? |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
@mhegazy Uh, the issue labels are wrong. See the actual issue. This is a feature request and it is quite actionable. |
Reopened as #17867 |
TypeScript Version: 2.2.1
Code
Based on the docs, this is not allowed:
Unfortunately, it seems to make this type (which is common amongst jss-in-css solutions) not expressible. Coming from flow, which handles index types by assuming they refer to the properties that are not explicitly typed, this is frustrating.
As it stands, you can workaround it with:
But this is not sound. It allows this:
This could potentially be solved with subtraction types if they allowed subtracting from
string
(and you were allowed to specify key types in this way):I asked about this on stackoverflow to confirm that I wasn't missing something. It seems I'm not, so I guess I'd consider this a suggestion/discussion starter, since it's probably not a "bug". Thanks!
The text was updated successfully, but these errors were encountered: