I'm working on the project that uses TypeScript and React and I'm trying to restrict the data based on interface assigned to state.
I have assigned the type IState interface to the state which has uiForm key assigns with type studentForm interface . But when I am assigning the wrong structured data or with wrong key which is not present in the studentForm Interface to uiForm key, it gets assigned without validating the type.
My code looks like this:
interface IProps {}
interface studentForm {
label: string,
type: string,
sequen: string
}
interface IState {
uiForm: Array < studentForm >
}
export default class AddStudent extends React.Component < IProps, IState > {
state: IState = {
uiForm: []
}
constructor(props: IProps) {
super(props);
}
componentDidMount() {
fetch('./assets/studentForm.json').then((res) => res.json())
.then((data) => {
this.setState({
uiForm: data
})
})
.catch(err => {
console.log(err);
})
}
}
I am trying to assign the uiForm with below object
studentForm.json:
{
"label":"Admission No.",
"type":"text",
"sequence":1
}
Ideally, it should not be assigned but it is assigning
What would be the proper way to assign the types to state/setState? Thank you.
setState
is not the crux here - if you look at the type signature of fetch
, you see that it returns a Response object with Body
interface like this:
interface Body {
...
json(): Promise<any>;
}
So data
effectively becomes any
typed and any
can be assigned to... anything..., which makes this.setState({ uiForm: data })
properly typed.
If you need to validate the fetch
result first, annotate data
with type unknown
and then do a run-time check with type guards (branching logic) or assertion functions (assert/invariant logic; TS 3.7). An assertion example:
export default class AddStudent extends React.Component<IProps, IState> {
...
componentDidMount() {
fetch('./assets/studentForm.json').then((res) => res.json())
// type data as unknown
.then((data: unknown) => {
// assertion function narrows data type or throws error
assertStudentFormArray(data)
// data type narrowed to Array<studentForm> here
this.setState({
uiForm: data
})
})
}
}
function assertStudentFormArray(args: any): asserts args is IState["uiForm"] {
// do your validation here ...
if (!Array.isArray(args)) throw new Error("Got no array...")
if (args.some(arg => !("label" in arg))) throw new Error("Got no studentform...")
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.