Description
I got an object like this:
const state = {
isFormOK: true,
fieldA: {
value: 'abc';
status: 'ok' | 'normal' | 'error';
errorText: '';
}
}
There could be many fields which have the same structure as the above fieldA
property, and in the code, I will actually use index property to access them because they are random. So I declared types like this:
export interface FieldState {
value: string;
status: 'ok' | 'normal' | 'error';
errorText: string;
}
export interface ComponentState {
isFormOK: boolean;
[fieldName: string]: FieldState
}
If you just swap those interface
with type
, then it works for flow.js
. Whereas can't do that in Typescript, because as the doc said:
While string index signatures are a powerful way to describe the “dictionary” pattern, they also enforce that all properties match their return type. This is because a string index declares that obj.property is also available as obj["property"].
And the error is:
Property isFormOK of type boolean is not assignable to string index type FieldState
I think it's fine, because when I access the state using an index, I might go to the case where the index equals isFormOK but I still want to use it like a FieldState. I know. But how could I solve it and type check this object?
Currently, we have 2 options:
-
Tried changing
[fieldName: string]: FieldState
to[fieldName: string]: {}
, then cast it toFieldState
everytime when use it. it works. But then the type for state doesn't convey the message where the real structure of this object. -
Tried changing
ComponentState
to
export type ComponentState =
{ isFormOK: boolean } &
{ [fieldName: string]: FieldState }
I currently use the 2nd approach.
What about just something like:
export interface ComponentState {
isFormOK: boolean;
[fieldName: string]: FieldState
}
Then the [fieldName: string]
will exclude isFormOK
when type checking the related instance.
Because we need some syntax to describe the actural structure of an object, so maybe reusing the existing syntax but expanding its underneath check will support it easily. Just like flow.js
.