I want to check if a typescript type or interface's fields are optional (or not).
export type Recommendation = {
id?: string,
name: string,
type?: string,
tt: string,
isin?: string,
issuer: string,
quantity?: number,
recDate: string,
createDate: string,
buyPrice?: number,
currentPrice?: number,
performance?: number,
comment?: string,
updateDate?: string,
updateRec?: string,
recentRec?: string,
}
for example name and issuer are not optional, most other fields are.
I now have dynamic input fields (for a submit form) created, and I want to set the "required" attribute on those inputs depending on if the types of the Recommendation
type required or not..
<Table responsive>
<thead>
<tr>
<th>#</th>
<th colSpan={10}>Create new data</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
{Array.from(Object.keys(sr)).map((colName, index) => (
<td key={index}><input required={ checkRequired ? true : false} name={colName} style={{width: "150px"}} type="text" placeholder={JSON.stringify(colName)} onChange={e => setFieldObj(e)} value={inputValue[colName]}></input></td>
))}
</tr>
</tbody>
</Table>
<button onClick={submitNewRecord}>Submit</button>
how can I do required={ checkRequired ? true : false}
with the typescript type?
CodePudding user response:
As @AlekseyL mentioned in the comments, you can't access type information at runtime. But you can, in some cases, access data at compile-time.
If you split your type into a const array of required fields, and a type where none of the fields are optional:
export const RequiredFields = ['name', 'tt', 'issuer', 'recDate', 'createDate'] as const;
type RecommendationFields = {
id: string,
name: string,
type: string,
tt: string,
isin: string,
issuer: string,
quantity: number,
recDate: string,
createDate: string,
buyPrice: number,
currentPrice: number,
performance: number,
comment: string,
updateDate: string,
updateRec: string,
recentRec: string,
};
You can use that information to reconstruct Recommendation
:
type OptionalFields = Exclude<keyof RecommendationFields, typeof RequiredFields[number]>;
type RecommendationOptional = { [key in OptionalFields]?: RecommendationFields[key] };
type RecommendationRequired = { [key in typeof RequiredFields[number]]: RecommendationFields[key] };
export type Recommendation = RecommendationOptional & RecommendationRequired;
And then at runtime you can test if a field is optional by checking that array:
function isFieldRequired(name: string) {
return RequiredFields.includes(name);
}