I am starting to develop an application with React and Typescript. I am newbie with the 2 things by the way.
I have a react component and some interface, I want the every field in that interface is required, but if one specific field is implemented the others are not required anymore.
In this case if I set "object" I would like to not need implement the other 2 fields.
interface ITextFieldProps {
label: string,
required: boolean,
object?: any
}
export default class TextField extends React.Component<ITextFieldProps, any> {
...
}
Hope someone can help, cheers!
EDIT
First of all I want to thank all the answers, I really learned a lot with each one of them. They helped me to understand my problem and to find the best solution.
The object that I will pass is a metadata so it will be only available in runtime after a http call. That being said, I cannot check and type it at dev time anyway.
So I solved my problem using the react props spread.
(Today it is not supported by typescript, but someday it will be someday hehe https://github.com/Microsoft/TypeScript/issues/2103):
export interface IMetadata {
label: string,
required: boolean
}
interface TextFieldProps extends IMetadata {
...
}
This way i can pass one object with the props spread and then when i call the label="" it will overwrite the label comming in {...this.metadata.nome} automatically:
<TextField {...this.metadata.nome} label="OverwriteLabel" />
EDIT 2
And as Daniel said: Unfortunately the type checking in JSX has a bug, see:
https://github.com/Microsoft/TypeScript/issues/10171
They plan to fix it for 2.1. Until then, this technique won't work for TSX. (When it is fixed, I will come back and update this answer.)
This is done in TypeScript with a union type.
interface TextFieldPropsA {
label: string,
required: boolean
}
interface TextFieldPropsB {
object: any
}
Here's how you can define a union of those:
type TextFieldProps = TextFieldPropsA | TextFieldPropsB;
This literally means it must be the first or the second type (it's exactly what you asked for in your question! We're "or"-ing two interfaces).
So:
// no good
const test1: TextFieldProps = { }
// no good, still missing the label
const test2: TextFieldProps = {
required: true
}
// this is fine
const test1: TextFieldProps = {
object: {}
}
(By the way, note that the I prefix is not widely used in TypeScript, because classes and function types are all interfaces so it really doesn't tell you anything useful.)
UPDATE However, you require this to define React props, so you can restrict what is allowed when using JSX syntax. Unfortunately the type checking in JSX has a bug, see:
https://github.com/Microsoft/TypeScript/issues/10171
They plan to fix it for 2.1. Until then, this technique won't work for TSX. (When it's fixed I'll come back and update this answer!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With